Merge "Only log a warning if it's an actual violation"
diff --git a/Android.bp b/Android.bp
index 13f6b6e..c89cc40 100644
--- a/Android.bp
+++ b/Android.bp
@@ -75,6 +75,7 @@
"core/*",
"libs/*",
"media/*",
+ "proto",
"tools/*",
"native/android",
"native/graphics/jni",
diff --git a/api/test-current.txt b/api/test-current.txt
index dd0e999..7930c47 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -32047,12 +32047,10 @@
public static final class StrictMode.ViolationInfo implements android.os.Parcelable {
ctor public StrictMode.ViolationInfo();
ctor public StrictMode.ViolationInfo(java.lang.Throwable, int);
- ctor public deprecated StrictMode.ViolationInfo(java.lang.String, java.lang.Throwable, int);
ctor public StrictMode.ViolationInfo(android.os.Parcel);
ctor public StrictMode.ViolationInfo(android.os.Parcel, boolean);
method public int describeContents();
method public void dump(android.util.Printer, java.lang.String);
- method public java.lang.String getMessagePrefix();
method public java.lang.String getStackTrace();
method public java.lang.String getViolationDetails();
method public void writeToParcel(android.os.Parcel, int);
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 280b1e80..351ec4e 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -501,7 +501,7 @@
public static final int PROCESS_STATE_SERVICE = 11;
/** @hide Process is in the background running a receiver. Note that from the
- * perspective of oom_adj receivers run at a higher foreground level, but for our
+ * perspective of oom_adj, receivers run at a higher foreground level, but for our
* prioritization here that is not necessary and putting them below services means
* many fewer changes in some process states as they receive broadcasts. */
public static final int PROCESS_STATE_RECEIVER = 12;
@@ -525,6 +525,20 @@
/** @hide Process does not exist. */
public static final int PROCESS_STATE_NONEXISTENT = 18;
+ // NOTE: If PROCESS_STATEs are added or changed, then new fields must be added
+ // to frameworks/base/core/proto/android/app/activitymanager.proto and the following method must
+ // be updated to correctly map between them.
+ /**
+ * Maps ActivityManager.PROCESS_STATE_ values to ActivityManagerProto.ProcessState enum.
+ *
+ * @param amInt a process state of the form ActivityManager.PROCESS_STATE_
+ * @return the value of the corresponding android.app.ActivityManagerProto's ProcessState enum.
+ * @hide
+ */
+ public static final int processStateAmToProto(int amInt) {
+ return amInt * 100;
+ }
+
/** @hide The lowest process state number */
public static final int MIN_PROCESS_STATE = PROCESS_STATE_PERSISTENT;
@@ -1886,7 +1900,7 @@
public List<RunningTaskInfo> getRunningTasks(int maxNum)
throws SecurityException {
try {
- return getService().getTasks(maxNum, 0);
+ return getService().getTasks(maxNum);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index 117854a..76a5612 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -115,7 +115,9 @@
in PersistableBundle persistentState, in CharSequence description);
String getCallingPackage(in IBinder token);
ComponentName getCallingActivity(in IBinder token);
- List<ActivityManager.RunningTaskInfo> getTasks(int maxNum, int flags);
+ List<ActivityManager.RunningTaskInfo> getTasks(int maxNum);
+ List<ActivityManager.RunningTaskInfo> getFilteredTasks(int maxNum, int ignoreActivityType,
+ int ignoreWindowingMode);
void moveTaskToFront(int task, int flags, in Bundle options);
void moveTaskBackwards(int task);
int getTaskForActivity(in IBinder token, in boolean onlyRoot);
diff --git a/core/java/android/app/WindowConfiguration.java b/core/java/android/app/WindowConfiguration.java
index 251863c..de27b4f 100644
--- a/core/java/android/app/WindowConfiguration.java
+++ b/core/java/android/app/WindowConfiguration.java
@@ -102,7 +102,7 @@
public static final int ACTIVITY_TYPE_STANDARD = 1;
/** Home/Launcher activity type. */
public static final int ACTIVITY_TYPE_HOME = 2;
- /** Recents/Overview activity type. */
+ /** Recents/Overview activity type. There is only one activity with this type in the system. */
public static final int ACTIVITY_TYPE_RECENTS = 3;
/** Assistant activity type. */
public static final int ACTIVITY_TYPE_ASSISTANT = 4;
diff --git a/core/java/android/net/metrics/DefaultNetworkEvent.java b/core/java/android/net/metrics/DefaultNetworkEvent.java
index 28cf42f..eb61c153 100644
--- a/core/java/android/net/metrics/DefaultNetworkEvent.java
+++ b/core/java/android/net/metrics/DefaultNetworkEvent.java
@@ -16,73 +16,43 @@
package android.net.metrics;
+import static android.net.ConnectivityManager.NETID_UNSET;
+
import android.net.NetworkCapabilities;
-import android.os.Parcel;
-import android.os.Parcelable;
/**
* An event recorded by ConnectivityService when there is a change in the default network.
* {@hide}
*/
-public final class DefaultNetworkEvent implements Parcelable {
+public class DefaultNetworkEvent {
+
// The ID of the network that has become the new default or NETID_UNSET if none.
- public final int netId;
+ public int netId = NETID_UNSET;
// The list of transport types of the new default network, for example TRANSPORT_WIFI, as
// defined in NetworkCapabilities.java.
- public final int[] transportTypes;
+ public int[] transportTypes = new int[0];
// The ID of the network that was the default before or NETID_UNSET if none.
- public final int prevNetId;
+ public int prevNetId = NETID_UNSET;
// Whether the previous network had IPv4/IPv6 connectivity.
- public final boolean prevIPv4;
- public final boolean prevIPv6;
-
- public DefaultNetworkEvent(int netId, int[] transportTypes,
- int prevNetId, boolean prevIPv4, boolean prevIPv6) {
- this.netId = netId;
- this.transportTypes = transportTypes;
- this.prevNetId = prevNetId;
- this.prevIPv4 = prevIPv4;
- this.prevIPv6 = prevIPv6;
- }
-
- private DefaultNetworkEvent(Parcel in) {
- this.netId = in.readInt();
- this.transportTypes = in.createIntArray();
- this.prevNetId = in.readInt();
- this.prevIPv4 = (in.readByte() > 0);
- this.prevIPv6 = (in.readByte() > 0);
- }
-
- @Override
- public void writeToParcel(Parcel out, int flags) {
- out.writeInt(netId);
- out.writeIntArray(transportTypes);
- out.writeInt(prevNetId);
- out.writeByte(prevIPv4 ? (byte) 1 : (byte) 0);
- out.writeByte(prevIPv6 ? (byte) 1 : (byte) 0);
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
+ public boolean prevIPv4;
+ public boolean prevIPv6;
@Override
public String toString() {
- String prevNetwork = String.valueOf(prevNetId);
- String newNetwork = String.valueOf(netId);
- if (prevNetId != 0) {
- prevNetwork += ":" + ipSupport();
- }
- if (netId != 0) {
- newNetwork += ":" + NetworkCapabilities.transportNamesOf(transportTypes);
- }
- return String.format("DefaultNetworkEvent(%s -> %s)", prevNetwork, newNetwork);
+ String prevNetwork = String.valueOf(prevNetId);
+ String newNetwork = String.valueOf(netId);
+ if (prevNetId != 0) {
+ prevNetwork += ":" + ipSupport();
+ }
+ if (netId != 0) {
+ newNetwork += ":" + NetworkCapabilities.transportNamesOf(transportTypes);
+ }
+ return String.format("DefaultNetworkEvent(%s -> %s)", prevNetwork, newNetwork);
}
private String ipSupport() {
if (prevIPv4 && prevIPv6) {
- return "DUAL";
+ return "IPv4v6";
}
if (prevIPv6) {
return "IPv6";
@@ -92,15 +62,4 @@
}
return "NONE";
}
-
- public static final Parcelable.Creator<DefaultNetworkEvent> CREATOR
- = new Parcelable.Creator<DefaultNetworkEvent>() {
- public DefaultNetworkEvent createFromParcel(Parcel in) {
- return new DefaultNetworkEvent(in);
- }
-
- public DefaultNetworkEvent[] newArray(int size) {
- return new DefaultNetworkEvent[size];
- }
- };
}
diff --git a/core/java/android/os/StrictMode.java b/core/java/android/os/StrictMode.java
index f52d94e..ee3e5bc 100644
--- a/core/java/android/os/StrictMode.java
+++ b/core/java/android/os/StrictMode.java
@@ -34,6 +34,7 @@
import android.util.Slog;
import android.view.IWindowManager;
+import com.android.internal.annotations.GuardedBy;
import com.android.internal.os.RuntimeInit;
import com.android.internal.util.FastPrintWriter;
import com.android.internal.util.HexDump;
@@ -1647,7 +1648,7 @@
private static class AndroidCloseGuardReporter implements CloseGuard.Reporter {
public void report(String message, Throwable allocationSite) {
- onVmPolicyViolation(message, allocationSite);
+ onVmPolicyViolation(allocationSite);
}
}
@@ -1686,7 +1687,7 @@
long instances = instanceCounts[i];
if (instances > limit) {
Throwable tr = new InstanceCountViolation(klass, instances, limit);
- onVmPolicyViolation(tr.getMessage(), tr);
+ onVmPolicyViolation(tr);
}
}
}
@@ -1810,22 +1811,24 @@
/** @hide */
public static void onSqliteObjectLeaked(String message, Throwable originStack) {
- onVmPolicyViolation(message, originStack);
+ Throwable t = new Throwable(message);
+ t.setStackTrace(originStack.getStackTrace());
+ onVmPolicyViolation(t);
}
/** @hide */
public static void onWebViewMethodCalledOnWrongThread(Throwable originStack) {
- onVmPolicyViolation(null, originStack);
+ onVmPolicyViolation(originStack);
}
/** @hide */
public static void onIntentReceiverLeaked(Throwable originStack) {
- onVmPolicyViolation(null, originStack);
+ onVmPolicyViolation(originStack);
}
/** @hide */
public static void onServiceConnectionLeaked(Throwable originStack) {
- onVmPolicyViolation(null, originStack);
+ onVmPolicyViolation(originStack);
}
/** @hide */
@@ -1834,7 +1837,7 @@
if ((sVmPolicy.mask & PENALTY_DEATH_ON_FILE_URI_EXPOSURE) != 0) {
throw new FileUriExposedException(message);
} else {
- onVmPolicyViolation(null, new Throwable(message));
+ onVmPolicyViolation(new Throwable(message));
}
}
@@ -1846,7 +1849,7 @@
+ location
+ " without permission grant flags; did you forget"
+ " FLAG_GRANT_READ_URI_PERMISSION?";
- onVmPolicyViolation(null, new Throwable(message));
+ onVmPolicyViolation(new Throwable(message));
}
/** @hide */
@@ -1876,10 +1879,9 @@
} catch (UnknownHostException ignored) {
}
}
-
+ msg += HexDump.dumpHexString(firstPacket).trim() + " ";
final boolean forceDeath = (sVmPolicy.mask & PENALTY_DEATH_ON_CLEARTEXT_NETWORK) != 0;
- onVmPolicyViolation(
- HexDump.dumpHexString(firstPacket).trim(), new Throwable(msg), forceDeath);
+ onVmPolicyViolation(new Throwable(msg), forceDeath);
}
/** @hide */
@@ -1889,24 +1891,23 @@
/** @hide */
public static void onUntaggedSocket() {
- onVmPolicyViolation(null, new Throwable(UNTAGGED_SOCKET_VIOLATION_MESSAGE));
+ onVmPolicyViolation(new Throwable(UNTAGGED_SOCKET_VIOLATION_MESSAGE));
}
// Map from VM violation fingerprint to uptime millis.
private static final HashMap<Integer, Long> sLastVmViolationTime = new HashMap<Integer, Long>();
/** @hide */
- public static void onVmPolicyViolation(String message, Throwable originStack) {
- onVmPolicyViolation(message, originStack, false);
+ public static void onVmPolicyViolation(Throwable originStack) {
+ onVmPolicyViolation(originStack, false);
}
/** @hide */
- public static void onVmPolicyViolation(
- String message, Throwable originStack, boolean forceDeath) {
+ public static void onVmPolicyViolation(Throwable originStack, boolean forceDeath) {
final boolean penaltyDropbox = (sVmPolicy.mask & PENALTY_DROPBOX) != 0;
final boolean penaltyDeath = ((sVmPolicy.mask & PENALTY_DEATH) != 0) || forceDeath;
final boolean penaltyLog = (sVmPolicy.mask & PENALTY_LOG) != 0;
- final ViolationInfo info = new ViolationInfo(message, originStack, sVmPolicy.mask);
+ final ViolationInfo info = new ViolationInfo(originStack, sVmPolicy.mask);
// Erase stuff not relevant for process-wide violations
info.numAnimationsRunning = 0;
@@ -2224,7 +2225,7 @@
// StrictMode not enabled.
return;
}
- ((AndroidBlockGuardPolicy) policy).onUnbufferedIO();
+ policy.onUnbufferedIO();
}
/** @hide */
@@ -2234,7 +2235,7 @@
// StrictMode not enabled.
return;
}
- ((AndroidBlockGuardPolicy) policy).onReadFromDisk();
+ policy.onReadFromDisk();
}
/** @hide */
@@ -2244,12 +2245,11 @@
// StrictMode not enabled.
return;
}
- ((AndroidBlockGuardPolicy) policy).onWriteToDisk();
+ policy.onWriteToDisk();
}
- // Guarded by StrictMode.class
- private static final HashMap<Class, Integer> sExpectedActivityInstanceCount =
- new HashMap<Class, Integer>();
+ @GuardedBy("StrictMode.class")
+ private static final HashMap<Class, Integer> sExpectedActivityInstanceCount = new HashMap<>();
/**
* Returns an object that is used to track instances of activites. The activity should store a
@@ -2324,7 +2324,7 @@
long instances = VMDebug.countInstancesOfClass(klass, false);
if (instances > limit) {
Throwable tr = new InstanceCountViolation(klass, instances, limit);
- onVmPolicyViolation(tr.getMessage(), tr);
+ onVmPolicyViolation(tr);
}
}
@@ -2336,9 +2336,6 @@
*/
@TestApi
public static final class ViolationInfo implements Parcelable {
- /** Some VM violations provide additional information outside the throwable. */
- @Nullable private final String mMessagePrefix;
-
/** Stack and violation details. */
@Nullable private final Throwable mThrowable;
@@ -2382,24 +2379,12 @@
/** Create an uninitialized instance of ViolationInfo */
public ViolationInfo() {
- mMessagePrefix = null;
mThrowable = null;
policy = 0;
}
- /** Create an instance of ViolationInfo. */
+ /** Create an instance of ViolationInfo initialized from an exception. */
public ViolationInfo(Throwable tr, int policy) {
- this(null, tr, policy);
- }
-
- /**
- * Create an instance of ViolationInfo initialized from an exception with a message prefix.
- *
- * @deprecated prefixes belong in the Throwable.
- */
- @Deprecated
- public ViolationInfo(String messagePrefix, Throwable tr, int policy) {
- this.mMessagePrefix = messagePrefix;
this.mThrowable = tr;
violationUptimeMillis = SystemClock.uptimeMillis();
this.policy = policy;
@@ -2462,17 +2447,7 @@
}
/**
- * A handful of VM violations provide extra information that should be presented before
- * {@link #getViolationDetails()}.
- *
- * @hide
- */
- @TestApi
- public String getMessagePrefix() {
- return mMessagePrefix != null ? mMessagePrefix : "";
- }
-
- /** If this violation has a useful stack trace.
+ * If this violation has a useful stack trace.
*
* @hide
*/
@@ -2552,7 +2527,6 @@
* should be removed.
*/
public ViolationInfo(Parcel in, boolean unsetGatheringBit) {
- mMessagePrefix = in.readString();
mThrowable = (Throwable) in.readSerializable();
int binderStackSize = in.readInt();
for (int i = 0; i < binderStackSize; i++) {
@@ -2576,7 +2550,6 @@
/** Save a ViolationInfo instance to a parcel. */
@Override
public void writeToParcel(Parcel dest, int flags) {
- dest.writeString(mMessagePrefix);
dest.writeSerializable(mThrowable);
dest.writeInt(mBinderStack.size());
for (Throwable t : mBinderStack) {
diff --git a/core/java/android/service/autofill/SaveInfo.java b/core/java/android/service/autofill/SaveInfo.java
index fde2416..9a1dcbb 100644
--- a/core/java/android/service/autofill/SaveInfo.java
+++ b/core/java/android/service/autofill/SaveInfo.java
@@ -535,14 +535,15 @@
* 16 digits, or 15 digits starting with 108:
*
* <pre class="prettyprint">
- * import android.service.autofill.Validators;
+ * import static android.service.autofill.Validators.and;
+ * import static android.service.autofill.Validators.or;
*
* Validator validator =
* and(
* new LuhnChecksumValidator(ccNumberId),
* or(
- * new RegexValidator(ccNumberId, Pattern.compile(""^\\d{16}$")),
- * new RegexValidator(ccNumberId, Pattern.compile(""^108\\d{12}$"))
+ * new RegexValidator(ccNumberId, Pattern.compile("^\\d{16}$")),
+ * new RegexValidator(ccNumberId, Pattern.compile("^108\\d{12}$"))
* )
* );
* </pre>
@@ -562,14 +563,14 @@
* 4 digits on each field:
*
* <pre class="prettyprint">
- * import android.service.autofill.Validators;
+ * import static android.service.autofill.Validators.and;
*
* Validator validator =
* and(
- * new RegexValidator(ccNumberId1, Pattern.compile(""^\\d{4}$")),
- * new RegexValidator(ccNumberId2, Pattern.compile(""^\\d{4}$")),
- * new RegexValidator(ccNumberId3, Pattern.compile(""^\\d{4}$")),
- * new RegexValidator(ccNumberId4, Pattern.compile(""^\\d{4}$"))
+ * new RegexValidator(ccNumberId1, Pattern.compile("^\\d{4}$")),
+ * new RegexValidator(ccNumberId2, Pattern.compile("^\\d{4}$")),
+ * new RegexValidator(ccNumberId3, Pattern.compile("^\\d{4}$")),
+ * new RegexValidator(ccNumberId4, Pattern.compile("^\\d{4}$"))
* );
* </pre>
*
diff --git a/core/java/android/webkit/MimeTypeMap.java b/core/java/android/webkit/MimeTypeMap.java
index 39874e8..3861695 100644
--- a/core/java/android/webkit/MimeTypeMap.java
+++ b/core/java/android/webkit/MimeTypeMap.java
@@ -37,7 +37,7 @@
}
/**
- * Returns the file extension or an empty string iff there is no
+ * Returns the file extension or an empty string if there is no
* extension. This method is a convenience method for obtaining the
* extension of a url and has undefined results for other Strings.
* @param url
@@ -76,7 +76,7 @@
/**
* Return {@code true} if the given MIME type has an entry in the map.
* @param mimeType A MIME type (i.e. text/plain)
- * @return {@code true} iff there is a mimeType entry in the map.
+ * @return {@code true} if there is a mimeType entry in the map.
*/
public boolean hasMimeType(String mimeType) {
return MimeUtils.hasMimeType(mimeType);
@@ -85,7 +85,7 @@
/**
* Return the MIME type for the given extension.
* @param extension A file extension without the leading '.'
- * @return The MIME type for the given extension or {@code null} iff there is none.
+ * @return The MIME type for the given extension or {@code null} if there is none.
*/
@Nullable
public String getMimeTypeFromExtension(String extension) {
@@ -100,7 +100,7 @@
/**
* Return {@code true} if the given extension has a registered MIME type.
* @param extension A file extension without the leading '.'
- * @return {@code true} iff there is an extension entry in the map.
+ * @return {@code true} if there is an extension entry in the map.
*/
public boolean hasExtension(String extension) {
return MimeUtils.hasExtension(extension);
@@ -111,7 +111,7 @@
* MIME types map to multiple extensions. This call will return the most
* common extension for the given MIME type.
* @param mimeType A MIME type (i.e. text/plain)
- * @return The extension for the given MIME type or {@code null} iff there is none.
+ * @return The extension for the given MIME type or {@code null} if there is none.
*/
@Nullable
public String getExtensionFromMimeType(String mimeType) {
diff --git a/core/java/android/webkit/URLUtil.java b/core/java/android/webkit/URLUtil.java
index c2f121a..84c000a 100644
--- a/core/java/android/webkit/URLUtil.java
+++ b/core/java/android/webkit/URLUtil.java
@@ -137,7 +137,7 @@
}
/**
- * @return {@code true} iff the url is correctly URL encoded
+ * @return {@code true} if the url is correctly URL encoded
*/
static boolean verifyURLEncoding(String url) {
int count = url.length();
@@ -171,14 +171,14 @@
}
/**
- * @return {@code true} iff the url is an asset file.
+ * @return {@code true} if the url is an asset file.
*/
public static boolean isAssetUrl(String url) {
return (null != url) && url.startsWith(ASSET_BASE);
}
/**
- * @return {@code true} iff the url is a resource file.
+ * @return {@code true} if the url is a resource file.
* @hide
*/
public static boolean isResourceUrl(String url) {
@@ -186,7 +186,7 @@
}
/**
- * @return {@code true} iff the url is a proxy url to allow cookieless network
+ * @return {@code true} if the url is a proxy url to allow cookieless network
* requests from a file url.
* @deprecated Cookieless proxy is no longer supported.
*/
@@ -196,7 +196,7 @@
}
/**
- * @return {@code true} iff the url is a local file.
+ * @return {@code true} if the url is a local file.
*/
public static boolean isFileUrl(String url) {
return (null != url) && (url.startsWith(FILE_BASE) &&
@@ -205,28 +205,28 @@
}
/**
- * @return {@code true} iff the url is an about: url.
+ * @return {@code true} if the url is an about: url.
*/
public static boolean isAboutUrl(String url) {
return (null != url) && url.startsWith("about:");
}
/**
- * @return {@code true} iff the url is a data: url.
+ * @return {@code true} if the url is a data: url.
*/
public static boolean isDataUrl(String url) {
return (null != url) && url.startsWith("data:");
}
/**
- * @return {@code true} iff the url is a javascript: url.
+ * @return {@code true} if the url is a javascript: url.
*/
public static boolean isJavaScriptUrl(String url) {
return (null != url) && url.startsWith("javascript:");
}
/**
- * @return {@code true} iff the url is an http: url.
+ * @return {@code true} if the url is an http: url.
*/
public static boolean isHttpUrl(String url) {
return (null != url) &&
@@ -235,7 +235,7 @@
}
/**
- * @return {@code true} iff the url is an https: url.
+ * @return {@code true} if the url is an https: url.
*/
public static boolean isHttpsUrl(String url) {
return (null != url) &&
@@ -244,7 +244,7 @@
}
/**
- * @return {@code true} iff the url is a network url.
+ * @return {@code true} if the url is a network url.
*/
public static boolean isNetworkUrl(String url) {
if (url == null || url.length() == 0) {
@@ -254,14 +254,14 @@
}
/**
- * @return {@code true} iff the url is a content: url.
+ * @return {@code true} if the url is a content: url.
*/
public static boolean isContentUrl(String url) {
return (null != url) && url.startsWith(CONTENT_BASE);
}
/**
- * @return {@code true} iff the url is valid.
+ * @return {@code true} if the url is valid.
*/
public static boolean isValidUrl(String url) {
if (url == null || url.length() == 0) {
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index dfc81b2..259bf60 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -1103,7 +1103,7 @@
/**
* Gets whether this WebView has a back history item.
*
- * @return {@code true} iff this WebView has a back history item
+ * @return {@code true} if this WebView has a back history item
*/
public boolean canGoBack() {
checkThread();
@@ -1121,7 +1121,7 @@
/**
* Gets whether this WebView has a forward history item.
*
- * @return {@code true} iff this WebView has a forward history item
+ * @return {@code true} if this WebView has a forward history item
*/
public boolean canGoForward() {
checkThread();
diff --git a/core/java/android/webkit/WebViewFactory.java b/core/java/android/webkit/WebViewFactory.java
index 48e427f..797bdfb 100644
--- a/core/java/android/webkit/WebViewFactory.java
+++ b/core/java/android/webkit/WebViewFactory.java
@@ -137,7 +137,7 @@
}
/**
- * Load the native library for the given package name iff that package
+ * Load the native library for the given package name if that package
* name is the same as the one providing the webview.
*/
public static int loadWebViewNativeLibraryFromPackage(String packageName,
diff --git a/core/jni/android_os_HwBinder.cpp b/core/jni/android_os_HwBinder.cpp
index 59b761f..c4f22ee 100644
--- a/core/jni/android_os_HwBinder.cpp
+++ b/core/jni/android_os_HwBinder.cpp
@@ -35,6 +35,7 @@
#include <hidl/HidlTransportSupport.h>
#include <hwbinder/ProcessState.h>
#include <nativehelper/ScopedLocalRef.h>
+#include <nativehelper/ScopedUtfChars.h>
#include <vintf/parse_string.h>
#include <utils/misc.h>
@@ -261,14 +262,9 @@
JNIEnv *env,
jobject thiz,
jstring serviceNameObj) {
- if (serviceNameObj == NULL) {
- jniThrowException(env, "java/lang/NullPointerException", NULL);
- return;
- }
-
- const char *serviceName = env->GetStringUTFChars(serviceNameObj, NULL);
- if (serviceName == NULL) {
- return; // XXX exception already pending?
+ ScopedUtfChars str(env, serviceNameObj);
+ if (str.c_str() == nullptr) {
+ return; // NPE will be pending.
}
sp<hardware::IBinder> binder = JHwBinder::GetNativeBinder(env, thiz);
@@ -284,15 +280,12 @@
return;
}
- Return<bool> ret = manager->add(serviceName, base);
-
- env->ReleaseStringUTFChars(serviceNameObj, serviceName);
- serviceName = NULL;
+ Return<bool> ret = manager->add(str.c_str(), base);
bool ok = ret.isOk() && ret;
if (ok) {
- LOG(INFO) << "Starting thread pool.";
+ LOG(INFO) << "HwBinder: Starting thread pool for " << str.c_str();
::android::hardware::ProcessState::self()->startThreadPool();
}
@@ -308,28 +301,23 @@
using ::android::hidl::base::V1_0::IBase;
using ::android::hardware::details::getRawServiceInternal;
- if (ifaceNameObj == NULL) {
- jniThrowException(env, "java/lang/NullPointerException", NULL);
- return NULL;
- }
- if (serviceNameObj == NULL) {
- jniThrowException(env, "java/lang/NullPointerException", NULL);
- return NULL;
+ std::string ifaceName;
+ {
+ ScopedUtfChars str(env, ifaceNameObj);
+ if (str.c_str() == nullptr) {
+ return nullptr; // NPE will be pending.
+ }
+ ifaceName = str.c_str();
}
- const char *ifaceNameCStr = env->GetStringUTFChars(ifaceNameObj, NULL);
- if (ifaceNameCStr == NULL) {
- return NULL; // XXX exception already pending?
+ std::string serviceName;
+ {
+ ScopedUtfChars str(env, serviceNameObj);
+ if (str.c_str() == nullptr) {
+ return nullptr; // NPE will be pending.
+ }
+ serviceName = str.c_str();
}
- std::string ifaceName(ifaceNameCStr);
- env->ReleaseStringUTFChars(ifaceNameObj, ifaceNameCStr);
-
- const char *serviceNameCStr = env->GetStringUTFChars(serviceNameObj, NULL);
- if (serviceNameCStr == NULL) {
- return NULL; // XXX exception already pending?
- }
- std::string serviceName(serviceNameCStr);
- env->ReleaseStringUTFChars(serviceNameObj, serviceNameCStr);
// TODO(b/67981006): true /* retry */
sp<IBase> ret = getRawServiceInternal(ifaceName, serviceName, false /* retry */, false /* getStub */);
@@ -340,7 +328,7 @@
return NULL;
}
- LOG(INFO) << "Starting thread pool.";
+ LOG(INFO) << "HwBinder: Starting thread pool for " << serviceName << "::" << ifaceName;
::android::hardware::ProcessState::self()->startThreadPool();
return JHwRemoteBinder::NewObject(env, service);
diff --git a/core/proto/android/app/activitymanager.proto b/core/proto/android/app/activitymanager.proto
new file mode 100644
index 0000000..e87499e
--- /dev/null
+++ b/core/proto/android/app/activitymanager.proto
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+syntax = "proto2";
+
+package android.app;
+
+option java_multiple_files = true;
+
+message ActivityManagerProto {
+
+ // ActivityManager.java PROCESS_STATEs
+ enum ProcessState {
+ // Order matters for process states, so values have been spaced to provide
+ // room for future additions.
+
+ // Not a real process state.
+ PROCESS_STATE_UNKNOWN = -100;
+ // Process is a persistent system process.
+ PROCESS_STATE_PERSISTENT = 0;
+ // Process is a persistent system process and is doing UI.
+ PROCESS_STATE_PERSISTENT_UI = 100;
+ // Process is hosting the current top activities. Note that this covers
+ // all activities that are visible to the user.
+ PROCESS_STATE_TOP = 200;
+ // Process is hosting a foreground service due to a system binding.
+ PROCESS_STATE_BOUND_FOREGROUND_SERVICE = 300;
+ // Process is hosting a foreground service.
+ PROCESS_STATE_FOREGROUND_SERVICE = 400;
+ // Same as PROCESS_STATE_TOP but while device is sleeping.
+ PROCESS_STATE_TOP_SLEEPING = 500;
+ // Process is important to the user, and something they are aware of.
+ PROCESS_STATE_IMPORTANT_FOREGROUND = 600;
+ // Process is important to the user, but not something they are aware of.
+ PROCESS_STATE_IMPORTANT_BACKGROUND = 700;
+ // Process is in the background transient so we will try to keep running.
+ PROCESS_STATE_TRANSIENT_BACKGROUND = 800;
+ // Process is in the background running a backup/restore operation.
+ PROCESS_STATE_BACKUP = 900;
+ // Process is in the background, but it can't restore its state so we want
+ // to try to avoid killing it.
+ PROCESS_STATE_HEAVY_WEIGHT = 1000;
+ // Process is in the background running a service. Unlike oom_adj, this
+ // level is used for both the normal running in background state and the
+ // executing operations state.
+ PROCESS_STATE_SERVICE = 1100;
+ // Process is in the background running a receiver. Note that from the
+ // perspective of oom_adj, receivers run at a higher foreground level, but
+ // for our prioritization here that is not necessary and putting them
+ // below services means many fewer changes in some process states as they
+ // receive broadcasts.
+ PROCESS_STATE_RECEIVER = 1200;
+ // Process is in the background but hosts the home activity.
+ PROCESS_STATE_HOME = 1300;
+ // Process is in the background but hosts the last shown activity.
+ PROCESS_STATE_LAST_ACTIVITY = 1400;
+ // Process is being cached for later use and contains activities.
+ PROCESS_STATE_CACHED_ACTIVITY = 1500;
+ // Process is being cached for later use and is a client of another cached
+ // process that contains activities.
+ PROCESS_STATE_CACHED_ACTIVITY_CLIENT = 1600;
+ // Process is being cached for later use and is empty.
+ PROCESS_STATE_CACHED_EMPTY = 1700;
+ // Process does not exist.
+ PROCESS_STATE_NONEXISTENT = 1800;
+ }
+}
diff --git a/core/proto/android/content/intent.proto b/core/proto/android/content/intent.proto
index 4f49744..3e5265a 100644
--- a/core/proto/android/content/intent.proto
+++ b/core/proto/android/content/intent.proto
@@ -15,15 +15,37 @@
*/
syntax = "proto2";
+package android.content;
+
option java_package = "android.content";
option java_multiple_files = true;
import "frameworks/base/core/proto/android/os/patternmatcher.proto";
-package android.content;
-
// Next Tag: 13
message IntentProto {
+ enum DockState {
+ // Used as an int value for Intent#EXTRA_DOCK_STATE to represent that
+ // the phone is not in any dock.
+ DOCK_STATE_UNDOCKED = 0;
+
+ // Used as an int value for Intent#EXTRA_DOCK_STATE to represent that
+ // the phone is in a desk dock.
+ DOCK_STATE_DESK = 1;
+
+ // Used as an int value for Intent#EXTRA_DOCK_STATE to represent that
+ // the phone is in a car dock.
+ DOCK_STATE_CAR = 2;
+
+ // Used as an int value for Intent#EXTRA_DOCK_STATE to represent that
+ // the phone is in a analog (low end) dock.
+ DOCK_STATE_LE_DESK = 3;
+
+ // Used as an int value for Intent#EXTRA_DOCK_STATE to represent that
+ // the phone is in a digital (high end) dock.
+ DOCK_STATE_HE_DESK = 4;
+ }
+
optional string action = 1;
repeated string categories = 2;
optional string data = 3;
diff --git a/core/proto/android/os/batterymanager.proto b/core/proto/android/os/batterymanager.proto
new file mode 100644
index 0000000..669bf2d
--- /dev/null
+++ b/core/proto/android/os/batterymanager.proto
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+syntax = "proto2";
+package android.os;
+
+option java_multiple_files = true;
+
+message BatteryManagerProto {
+ enum PlugType {
+ PLUG_TYPE_NONE = 0;
+ PLUG_TYPE_AC = 1;
+ PLUG_TYPE_USB = 2;
+ PLUG_TYPE_WIRELESS = 4;
+ }
+}
diff --git a/core/proto/android/os/incident.proto b/core/proto/android/os/incident.proto
index 0887f03..f716ffe 100644
--- a/core/proto/android/os/incident.proto
+++ b/core/proto/android/os/incident.proto
@@ -20,6 +20,7 @@
import "frameworks/base/libs/incident/proto/android/privacy.proto";
import "frameworks/base/libs/incident/proto/android/section.proto";
+import "frameworks/base/core/proto/android/server/powermanagerservice.proto";
import "frameworks/base/core/proto/android/service/appwidget.proto";
import "frameworks/base/core/proto/android/service/battery.proto";
import "frameworks/base/core/proto/android/service/batterystats.proto";
@@ -28,7 +29,6 @@
import "frameworks/base/core/proto/android/service/netstats.proto";
import "frameworks/base/core/proto/android/service/notification.proto";
import "frameworks/base/core/proto/android/service/package.proto";
-import "frameworks/base/core/proto/android/service/power.proto";
import "frameworks/base/core/proto/android/service/print.proto";
import "frameworks/base/core/proto/android/service/procstats.proto";
import "frameworks/base/core/proto/android/server/activitymanagerservice.proto";
@@ -106,7 +106,11 @@
(section).args = "package --proto"
];
- optional android.service.power.PowerServiceDumpProto power = 3009;
+ optional com.android.server.power.PowerManagerServiceDumpProto power = 3009 [
+ (section).type = SECTION_DUMPSYS,
+ (section).args = "power --proto"
+ ];
+
optional android.service.print.PrintServiceDumpProto print = 3010;
optional android.service.procstats.ProcessStatsServiceDumpProto procstats = 3011 [
diff --git a/core/proto/android/os/powermanager.proto b/core/proto/android/os/powermanager.proto
index 3bfe5d6..e9f409d 100644
--- a/core/proto/android/os/powermanager.proto
+++ b/core/proto/android/os/powermanager.proto
@@ -15,10 +15,10 @@
*/
syntax = "proto2";
-option java_multiple_files = true;
-
package android.os;
+option java_multiple_files = true;
+
message PowerManagerProto {
/* User activity events in PowerManager.java. */
enum UserActivityEvent {
@@ -31,4 +31,84 @@
// Accessibility taking action on behalf of user.
USER_ACTIVITY_EVENT_ACCESSIBILITY = 3;
}
+
+ enum WakeLockLevel {
+ // NOTE: Wake lock levels were previously defined as a bit field, except
+ // that only a few combinations were actually supported so the bit field
+ // was removed. This explains why the numbering scheme is so odd. If
+ // adding a new wake lock level, any unused value can be used.
+
+ // Ensures that the CPU is running; the screen and keyboard backlight
+ // will be allowed to go off.
+ PARTIAL_WAKE_LOCK = 1;
+
+ // Ensures that the screen is on (but may be dimmed); the keyboard
+ // backlight will be allowed to go off. If the user presses the power
+ // button, then the SCREEN_DIM_WAKE_LOCK will be implicitly released by
+ // the system, causing both the screen and the CPU to be turned off.
+ SCREEN_DIM_WAKE_LOCK = 6 [deprecated = true];
+
+ // Ensures that the screen is on at full brightness; the keyboard
+ // backlight will be allowed to go off. If the user presses the power
+ // button, then the SCREEN_BRIGHT_WAKE_LOCK will be implicitly released
+ // by the system, causing both the screen and the CPU to be turned off.
+ SCREEN_BRIGHT_WAKE_LOCK = 10 [deprecated = true];
+
+ // Ensures that the screen and keyboard backlight are on at full
+ // brightness. If the user presses the power button, then the
+ // FULL_WAKE_LOCK will be implicitly released by the system, causing
+ // both the screen and the CPU to be turned off.
+ FULL_WAKE_LOCK = 26 [deprecated = true];
+
+ // Turns the screen off when the proximity sensor activates. If the
+ // proximity sensor detects that an object is nearby, the screen turns
+ // off immediately. Shortly after the object moves away, the screen
+ // turns on again.
+ // A proximity wake lock does not prevent the device from falling asleep
+ // unlike FULL_WAKE_LOCK, SCREEN_BRIGHT_WAKE_LOCK and
+ // SCREEN_DIM_WAKE_LOCK. If there is no user activity and no other wake
+ // locks are held, then the device will fall asleep (and lock) as usual.
+ // However, the device will not fall asleep while the screen has been
+ // turned off by the proximity sensor because it effectively counts as
+ // ongoing user activity.
+ PROXIMITY_SCREEN_OFF_WAKE_LOCK = 32;
+
+ // Put the screen in a low power state and allow the CPU to suspend if
+ // no other wake locks are held. This is used by the dream manager to
+ // implement doze mode. It currently has no effect unless the power
+ // manager is in the dozing state.
+ DOZE_WAKE_LOCK = 64;
+
+ // Keep the device awake enough to allow drawing to occur. This is used
+ // by the window manager to allow applications to draw while the system
+ // is dozing. It currently has no effect unless the power manager is in
+ // the dozing state.
+ DRAW_WAKE_LOCK = 128;
+ }
+}
+
+message PowerManagerInternalProto {
+ // Enum values gotten from PowerManagerInternal.java
+ enum Wakefulness {
+ // The device is asleep. It can only be awoken by a call to wakeUp().
+ // The screen should be off or in the process of being turned off by the
+ // display controller. The device typically passes through the dozing
+ // state first.
+ WAKEFULNESS_ASLEEP = 0;
+ // The device is fully awake. It can be put to sleep by a call to
+ // goToSleep(). When the user activity timeout expires, the device may
+ // start dreaming or go to sleep.
+ WAKEFULNESS_AWAKE = 1;
+ // The device is dreaming. It can be awoken by a call to wakeUp(), which
+ // ends the dream. The device goes to sleep when goToSleep() is called,
+ // when the dream ends, or when unplugged. User activity may brighten
+ // the screen but does not end the dream.
+ WAKEFULNESS_DREAMING = 2;
+ // The device is dozing. It is almost asleep but is allowing a special
+ // low-power "doze" dream to run which keeps the display on but lets the
+ // application processor suspend. It can be awoken by a call to wakeUp()
+ // which ends the dream. The device fully goes to sleep if the dream
+ // cannot be started or ends on its own.
+ WAKEFULNESS_DOZING = 3;
+ }
}
diff --git a/core/proto/android/providers/settings.proto b/core/proto/android/providers/settings.proto
index f092713..3411c6a 100644
--- a/core/proto/android/providers/settings.proto
+++ b/core/proto/android/providers/settings.proto
@@ -599,6 +599,14 @@
optional bool default_from_system = 6;
}
+message SettingsProto {
+ // Enum values gotten from Settings.java
+ enum ScreenBrightnessMode {
+ SCREEN_BRIGHTNESS_MODE_MANUAL = 0;
+ SCREEN_BRIGHTNESS_MODE_AUTOMATIC = 1;
+ }
+}
+
message SettingsOperationProto {
// When the operation happened
optional int64 timestamp = 1;
diff --git a/core/proto/android/service/power.proto b/core/proto/android/server/powermanagerservice.proto
similarity index 73%
rename from core/proto/android/service/power.proto
rename to core/proto/android/server/powermanagerservice.proto
index 5d53847..d442acf 100644
--- a/core/proto/android/service/power.proto
+++ b/core/proto/android/server/powermanagerservice.proto
@@ -15,16 +15,22 @@
*/
syntax = "proto2";
-package android.service.power;
+package com.android.server.power;
option java_multiple_files = true;
-option java_outer_classname = "PowerServiceProto";
+import "frameworks/base/core/proto/android/app/activitymanager.proto";
+import "frameworks/base/core/proto/android/content/intent.proto";
+import "frameworks/base/core/proto/android/os/batterymanager.proto";
import "frameworks/base/core/proto/android/os/looper.proto";
+import "frameworks/base/core/proto/android/os/powermanager.proto";
import "frameworks/base/core/proto/android/os/worksource.proto";
-import "frameworks/base/core/proto/android/service/wirelesschargerdetector.proto";
+import "frameworks/base/core/proto/android/providers/settings.proto";
+import "frameworks/base/core/proto/android/server/wirelesschargerdetector.proto";
+import "frameworks/base/core/proto/android/view/display.proto";
-message PowerServiceDumpProto {
+message PowerManagerServiceDumpProto {
+ // A com.android.server.power.PowerManagerService.Constants object.
message ConstantsProto {
optional bool is_no_cached_wake_locks = 1;
}
@@ -44,79 +50,14 @@
optional bool is_screen_dim = 2;
optional bool is_screen_dream = 3;
}
- message UidProto {
- // Enum values gotten from ActivityManager.java
- enum ProcessState {
- // Process is a persistent system process.
- PROCESS_STATE_PERSISTENT = 0;
- // Process is a persistent system process and is doing UI.
- PROCESS_STATE_PERSISTENT_UI = 1;
- // Process is hosting the current top activities. Note that this
- // covers all activities that are visible to the user.
- PROCESS_STATE_TOP = 2;
- // Process is hosting a foreground service due to a system binding.
- PROCESS_STATE_BOUND_FOREGROUND_SERVICE = 3;
- // Process is hosting a foreground service.
- PROCESS_STATE_FOREGROUND_SERVICE = 4;
- // Same as {@link #PROCESS_STATE_TOP} but while device is sleeping.
- PROCESS_STATE_TOP_SLEEPING = 5;
- // Process is important to the user, and something they are aware of.
- PROCESS_STATE_IMPORTANT_FOREGROUND = 6;
- // Process is important to the user, but not something they are aware of.
- PROCESS_STATE_IMPORTANT_BACKGROUND = 7;
- // Process is in the background running a backup/restore operation.
- PROCESS_STATE_BACKUP = 8;
- // Process is in the background, but it can't restore its state so
- // we want to try to avoid killing it.
- PROCESS_STATE_HEAVY_WEIGHT = 9;
- // Process is in the background running a service.
- PROCESS_STATE_SERVICE = 10;
- // Process is in the background running a receiver.
- PROCESS_STATE_RECEIVER = 11;
- // Process is in the background but hosts the home activity.
- PROCESS_STATE_HOME = 12;
- // Process is in the background but hosts the last shown activity.
- PROCESS_STATE_LAST_ACTIVITY = 13;
- // Process is being cached for later use and contains activities.
- PROCESS_STATE_CACHED_ACTIVITY = 14;
- // Process is being cached for later use and is a client of another
- // cached process that contains activities.
- PROCESS_STATE_CACHED_ACTIVITY_CLIENT = 15;
- // Process is being cached for later use and is empty.
- PROCESS_STATE_CACHED_EMPTY = 16;
- // Process does not exist.
- PROCESS_STATE_NONEXISTENT = 17;
- }
+ // A com.android.server.power.PowerManagerService.UidState object.
+ message UidStateProto {
optional int32 uid = 1;
optional string uid_string = 2;
optional bool is_active = 3;
optional int32 num_wake_locks = 4;
optional bool is_process_state_unknown = 5;
- optional ProcessState process_state = 6;
- }
-
- // Enum values gotten from PowerManagerInternal.java
- enum Wakefulness {
- WAKEFULNESS_ASLEEP = 0;
- WAKEFULNESS_AWAKE = 1;
- WAKEFULNESS_DREAMING = 2;
- WAKEFULNESS_DOZING = 3;
- WAKEFULNESS_UNKNOWN = 4;
- }
- // Enum values gotten from BatteryManager.java
- enum PlugType {
- PLUG_TYPE_NONE = 0;
- PLUG_TYPE_PLUGGED_AC = 1;
- PLUG_TYPE_PLUGGED_USB = 2;
- PLUG_TYPE_PLUGGED_WIRELESS = 4;
- }
- // Enum values gotten from Intent.java
- enum DockState {
- DOCK_STATE_UNDOCKED = 0;
- DOCK_STATE_DESK = 1;
- DOCK_STATE_CAR = 2;
- DOCK_STATE_LE_DESK = 3;
- DOCK_STATE_HE_DESK = 4;
+ optional .android.app.ActivityManagerProto.ProcessState process_state = 6;
}
optional ConstantsProto constants = 1;
@@ -124,18 +65,18 @@
// changed and need to be recalculated.
optional int32 dirty = 2;
// Indicates whether the device is awake or asleep or somewhere in between.
- optional Wakefulness wakefulness = 3;
+ optional .android.os.PowerManagerInternalProto.Wakefulness wakefulness = 3;
optional bool is_wakefulness_changing = 4;
// True if the device is plugged into a power source.
optional bool is_powered = 5;
// The current plug type
- optional PlugType plug_type = 6;
+ optional .android.os.BatteryManagerProto.PlugType plug_type = 6;
// The current battery level percentage.
optional int32 battery_level = 7;
// The battery level percentage at the time the dream started.
optional int32 battery_level_when_dream_started = 8;
// The current dock state.
- optional DockState dock_state = 9;
+ optional .android.content.IntentProto.DockState dock_state = 9;
// True if the device should stay on.
optional bool is_stay_on = 10;
// True if the proximity sensor reads a positive result.
@@ -215,8 +156,8 @@
// Some uids have actually changed while mUidsChanging was true.
optional bool are_uids_changed = 45;
// List of UIDs and their states
- repeated UidProto uids = 46;
- optional android.os.LooperProto looper = 47;
+ repeated UidStateProto uid_states = 46;
+ optional .android.os.LooperProto looper = 47;
// List of all wake locks acquired by applications.
repeated WakeLockProto wake_locks = 48;
// List of all suspend blockers.
@@ -224,11 +165,13 @@
optional WirelessChargerDetectorProto wireless_charger_detector = 50;
}
+// A com.android.server.power.PowerManagerService.SuspendBlockerImpl object.
message SuspendBlockerProto {
optional string name = 1;
optional int32 reference_count = 2;
}
+// A com.android.server.power.PowerManagerService.WakeLock object.
message WakeLockProto {
message WakeLockFlagsProto {
// Turn the screen on when the wake lock is acquired.
@@ -238,27 +181,7 @@
optional bool is_on_after_release = 2;
}
- // Enum values gotten from PowerManager.java
- enum LockLevel {
- WAKE_LOCK_INVALID = 0;
- // Ensures that the CPU is running.
- PARTIAL_WAKE_LOCK = 1;
- // Ensures that the screen is on (but may be dimmed).
- SCREEN_DIM_WAKE_LOCK = 6;
- // Ensures that the screen is on at full brightness.
- SCREEN_BRIGHT_WAKE_LOCK = 10;
- // Ensures that the screen and keyboard backlight are on at full brightness.
- FULL_WAKE_LOCK = 26;
- // Turns the screen off when the proximity sensor activates.
- PROXIMITY_SCREEN_OFF_WAKE_LOCK = 32;
- // Put the screen in a low power state and allow the CPU to suspend
- // if no other wake locks are held.
- DOZE_WAKE_LOCK = 64;
- // Keep the device awake enough to allow drawing to occur.
- DRAW_WAKE_LOCK = 128;
- }
-
- optional LockLevel lock_level = 1;
+ optional .android.os.PowerManagerProto.WakeLockLevel lock_level = 1;
optional string tag = 2;
optional WakeLockFlagsProto flags = 3;
optional bool is_disabled = 4;
@@ -269,7 +192,7 @@
optional int32 uid = 7;
// Owner PID
optional int32 pid = 8;
- optional android.os.WorkSourceProto work_source = 9;
+ optional .android.os.WorkSourceProto work_source = 9;
}
message PowerServiceSettingsAndConfigurationDumpProto {
@@ -285,22 +208,6 @@
optional int32 setting_for_vr_default = 4;
}
- // Enum values gotten from Settings.java
- enum ScreenBrightnessMode {
- SCREEN_BRIGHTNESS_MODE_MANUAL = 0;
- SCREEN_BRIGHTNESS_MODE_AUTOMATIC = 1;
- }
- // Enum values gotten from Display.java
- enum DisplayState {
- DISPLAY_STATE_UNKNOWN = 0;
- DISPLAY_STATE_OFF = 1;
- DISPLAY_STATE_ON = 2;
- DISPLAY_STATE_DOZE = 3;
- DISPLAY_STATE_DOZE_SUSPEND = 4;
- DISPLAY_STATE_VR = 5;
- }
-
-
// True to decouple auto-suspend mode from the display state.
optional bool is_decouple_hal_auto_suspend_mode_from_display_config = 1;
// True to decouple interactive mode from the display state.
@@ -371,7 +278,7 @@
// Use 0 if there is no adjustment.
optional float screen_auto_brightness_adjustment_setting = 31;
// The screen brightness mode.
- optional ScreenBrightnessMode screen_brightness_mode_setting = 32;
+ optional .android.providers.settings.SettingsProto.ScreenBrightnessMode screen_brightness_mode_setting = 32;
// The screen brightness setting override from the window manager
// to allow the current foreground activity to override the brightness.
// Use -1 to disable.
@@ -393,7 +300,7 @@
// Use NaN to disable.
optional float temporary_screen_auto_brightness_adjustment_setting_override = 37;
// The screen state to use while dozing.
- optional DisplayState doze_screen_state_override_from_dream_manager = 38;
+ optional .android.view.DisplayProto.DisplayState doze_screen_state_override_from_dream_manager = 38;
// The screen brightness to use while dozing.
optional float dozed_screen_brightness_override_from_dream_manager = 39;
// Screen brightness settings limits.
diff --git a/core/proto/android/service/wirelesschargerdetector.proto b/core/proto/android/server/wirelesschargerdetector.proto
similarity index 97%
rename from core/proto/android/service/wirelesschargerdetector.proto
rename to core/proto/android/server/wirelesschargerdetector.proto
index bd697c8..89cf2f8 100644
--- a/core/proto/android/service/wirelesschargerdetector.proto
+++ b/core/proto/android/server/wirelesschargerdetector.proto
@@ -15,7 +15,7 @@
*/
syntax = "proto2";
-package android.service.power;
+package com.android.server.power;
option java_multiple_files = true;
@@ -46,4 +46,4 @@
optional VectorProto first_sample = 9;
// The value of the last sample that was collected.
optional VectorProto last_sample = 10;
-}
\ No newline at end of file
+}
diff --git a/core/proto/android/service/battery.proto b/core/proto/android/service/battery.proto
index 998a808..8382b82 100644
--- a/core/proto/android/service/battery.proto
+++ b/core/proto/android/service/battery.proto
@@ -20,13 +20,9 @@
option java_multiple_files = true;
option java_outer_classname = "BatteryServiceProto";
+import "frameworks/base/core/proto/android/os/batterymanager.proto";
+
message BatteryServiceDumpProto {
- enum BatteryPlugged {
- BATTERY_PLUGGED_NONE = 0;
- BATTERY_PLUGGED_AC = 1;
- BATTERY_PLUGGED_USB = 2;
- BATTERY_PLUGGED_WIRELESS = 4;
- }
enum BatteryStatus {
BATTERY_STATUS_INVALID = 0;
BATTERY_STATUS_UNKNOWN = 1;
@@ -49,7 +45,7 @@
// If true: UPDATES STOPPED -- use 'reset' to restart
optional bool are_updates_stopped = 1;
// Plugged status of power sources
- optional BatteryPlugged plugged = 2;
+ optional android.os.BatteryManagerProto.PlugType plugged = 2;
// Max current in microamperes
optional int32 max_charging_current = 3;
// Max voltage
diff --git a/core/proto/android/view/display.proto b/core/proto/android/view/display.proto
new file mode 100644
index 0000000..210c6d1
--- /dev/null
+++ b/core/proto/android/view/display.proto
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+syntax = "proto2";
+package android.view;
+
+option java_multiple_files = true;
+
+message DisplayProto {
+ enum DisplayState {
+ // The display state is unknown.
+ DISPLAY_STATE_UNKNOWN = 0;
+ // The display state is off.
+ DISPLAY_STATE_OFF = 1;
+ // The display state is on.
+ DISPLAY_STATE_ON = 2;
+ // The display is dozing in a low power state; it is still on but is
+ // optimized for showing system-provided content while the device is
+ // non-interactive.
+ DISPLAY_STATE_DOZE = 3;
+ // The display is dozing in a suspended low power state; it is still on
+ // but is optimized for showing static system-provided content while the
+ // device is non-interactive.
+ DISPLAY_STATE_DOZE_SUSPEND = 4;
+ // The display is on and optimized for VR mode.
+ DISPLAY_STATE_VR = 5;
+ }
+}
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 0e90287..be0f6d9 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -1334,7 +1334,7 @@
split that contains the defined component. -->
<attr name="splitName" format="string" />
- <!-- Specifies the target sandbox this app wants to use. Higher sanbox versions
+ <!-- Specifies the target sandbox this app wants to use. Higher sandbox versions
will have increasing levels of security.
<p>The default value of this attribute is <code>1</code>. -->
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 571aad9..e5f3aaf 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2356,6 +2356,10 @@
property. If this is false, then the following recents config flags are ignored. -->
<bool name="config_hasRecents">true</bool>
+ <!-- Component name for the activity that will be presenting the Recents UI, which will receive
+ special permissions for API related to fetching and presenting recent tasks. -->
+ <string name="config_recentsComponentName" translatable="false">com.android.systemui/.recents.RecentsActivity</string>
+
<!-- The minimum number of visible recent tasks to be presented to the user through the
SystemUI. Can be -1 if there is no minimum limit. -->
<integer name="config_minNumVisibleRecentTasks_grid">-1</integer>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 896de53..3dff9d7 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -311,6 +311,7 @@
<java-symbol type="bool" name="config_enableMultiUserUI"/>
<java-symbol type="bool" name="config_disableUsbPermissionDialogs"/>
<java-symbol type="bool" name="config_hasRecents" />
+ <java-symbol type="string" name="config_recentsComponentName" />
<java-symbol type="integer" name="config_minNumVisibleRecentTasks_lowRam" />
<java-symbol type="integer" name="config_maxNumVisibleRecentTasks_lowRam" />
<java-symbol type="integer" name="config_minNumVisibleRecentTasks_grid" />
diff --git a/location/java/android/location/GnssClock.java b/location/java/android/location/GnssClock.java
index 25d247d..671c57c 100644
--- a/location/java/android/location/GnssClock.java
+++ b/location/java/android/location/GnssClock.java
@@ -332,6 +332,9 @@
/**
* Gets the clock's Drift in nanoseconds per second.
*
+ * <p>This value is the instantaneous time-derivative of the value provided by
+ * {@link #getBiasNanos()}.
+ *
* <p>A positive value indicates that the frequency is higher than the nominal (e.g. GPS master
* clock) frequency. The error estimate for this reported drift is
* {@link #getDriftUncertaintyNanosPerSecond()}.
diff --git a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
index 312b990..c92562b 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
@@ -599,8 +599,8 @@
private boolean isSettingsShown() {
List<RunningTaskInfo> runningTasks;
try {
- runningTasks = mActivityManager.getTasks(1, 0);
- if (runningTasks == null || runningTasks.size() == 0) {
+ runningTasks = mActivityManager.getTasks(1);
+ if (runningTasks.isEmpty()) {
return false;
}
} catch (RemoteException e) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
index 87f24fd..55ec5e7 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
@@ -200,25 +200,17 @@
*/
public ActivityManager.RunningTaskInfo getRunningTask() {
// Note: The set of running tasks from the system is ordered by recency
- List<ActivityManager.RunningTaskInfo> tasks = mAm.getRunningTasks(10);
- if (tasks == null || tasks.isEmpty()) {
+ try {
+ List<ActivityManager.RunningTaskInfo> tasks = mIam.getFilteredTasks(1,
+ ACTIVITY_TYPE_RECENTS /* ignoreActivityType */,
+ WINDOWING_MODE_PINNED /* ignoreWindowingMode */);
+ if (tasks.isEmpty()) {
+ return null;
+ }
+ return tasks.get(0);
+ } catch (RemoteException e) {
return null;
}
-
- // Find the first task in a valid stack, we ignore everything from the Recents and PiP
- // stacks
- for (int i = 0; i < tasks.size(); i++) {
- final ActivityManager.RunningTaskInfo task = tasks.get(i);
- final WindowConfiguration winConfig = task.configuration.windowConfiguration;
- if (winConfig.getActivityType() == ACTIVITY_TYPE_RECENTS) {
- continue;
- }
- if (winConfig.getWindowingMode() == WINDOWING_MODE_PINNED) {
- continue;
- }
- return task;
- }
- return null;
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java
index 25c2fc9..7442904 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java
@@ -302,11 +302,6 @@
*/
private List<AppTransitionAnimationSpec> composeAnimationSpecs(final Task task,
final TaskStackView stackView, int windowingMode, int activityType, Rect windowRect) {
- if (activityType == ACTIVITY_TYPE_RECENTS || activityType == ACTIVITY_TYPE_HOME
- || windowingMode == WINDOWING_MODE_PINNED) {
- return null;
- }
-
// Calculate the offscreen task rect (for tasks that are not backed by views)
TaskView taskView = stackView.getChildViewForTask(task);
TaskStackLayoutAlgorithm stackLayout = stackView.getStackAlgorithm();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
index 68fe9a8..84b7015 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
@@ -29,7 +29,6 @@
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewAnimationUtils;
-import android.view.ViewConfiguration;
import android.view.accessibility.AccessibilityManager;
import android.view.animation.Interpolator;
import android.view.animation.PathInterpolator;
@@ -173,12 +172,12 @@
private int mOverrideTint;
private float mOverrideAmount;
private boolean mShadowHidden;
- private boolean mWasActivatedOnDown;
/**
* Similar to mDimmed but is also true if it's not dimmable but should be
*/
private boolean mNeedsDimming;
private int mDimmedAlpha;
+ private boolean mBlockNextTouch;
public ActivatableNotificationView(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -204,7 +203,7 @@
} else {
makeInactive(true /* animate */);
}
- }, this::performClick, this::handleSlideBack, mFalsingManager::onNotificationDoubleTap);
+ }, super::performClick, this::handleSlideBack, mFalsingManager::onNotificationDoubleTap);
}
@Override
@@ -241,9 +240,15 @@
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
- if (mNeedsDimming && !mActivated && ev.getActionMasked() == MotionEvent.ACTION_DOWN
+ if (mNeedsDimming && ev.getActionMasked() == MotionEvent.ACTION_DOWN
&& disallowSingleClick(ev) && !isTouchExplorationEnabled()) {
- return true;
+ if (!mActivated) {
+ return true;
+ } else if (!mDoubleTapHelper.isWithinDoubleTapSlop(ev)) {
+ mBlockNextTouch = true;
+ makeInactive(true /* animate */);
+ return true;
+ }
}
return super.onInterceptTouchEvent(ev);
}
@@ -263,10 +268,11 @@
@Override
public boolean onTouchEvent(MotionEvent event) {
boolean result;
- if (event.getAction() == MotionEvent.ACTION_DOWN) {
- mWasActivatedOnDown = mActivated;
+ if (mBlockNextTouch) {
+ mBlockNextTouch = false;
+ return false;
}
- if ((mNeedsDimming && !mActivated) && !isTouchExplorationEnabled() && isInteractive()) {
+ if (mNeedsDimming && !isTouchExplorationEnabled() && isInteractive()) {
boolean wasActivated = mActivated;
result = handleTouchEventDimmed(event);
if (wasActivated && result && event.getAction() == MotionEvent.ACTION_UP) {
@@ -312,7 +318,7 @@
@Override
public boolean performClick() {
- if (mWasActivatedOnDown || !mNeedsDimming || isTouchExplorationEnabled()) {
+ if (!mNeedsDimming || isTouchExplorationEnabled()) {
return super.performClick();
}
return false;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DoubleTapHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DoubleTapHelper.java
index dcb6a38..0d62703 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DoubleTapHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DoubleTapHelper.java
@@ -142,7 +142,7 @@
&& Math.abs(event.getY() - mDownY) < mTouchSlop;
}
- private boolean isWithinDoubleTapSlop(MotionEvent event) {
+ public boolean isWithinDoubleTapSlop(MotionEvent event) {
if (!mActivated) {
// If we're not activated there's no double tap slop to satisfy.
return true;
diff --git a/proto/Android.bp b/proto/Android.bp
new file mode 100644
index 0000000..95f453c
--- /dev/null
+++ b/proto/Android.bp
@@ -0,0 +1,17 @@
+java_library_static {
+ name: "framework-protos",
+ host_supported: true,
+ proto: {
+ type: "nano",
+ },
+ srcs: ["src/**/*.proto"],
+ no_framework_libs: true,
+ target: {
+ android: {
+ jarjar_rules: "jarjar-rules.txt",
+ },
+ host: {
+ static_libs: ["libprotobuf-java-nano"],
+ },
+ },
+}
diff --git a/proto/Android.mk b/proto/Android.mk
deleted file mode 100644
index 1c03d16..0000000
--- a/proto/Android.mk
+++ /dev/null
@@ -1,33 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := framework-protos
-
-LOCAL_PROTOC_OPTIMIZE_TYPE := nano
-LOCAL_SRC_FILES:= $(call all-proto-files-under, src)
-LOCAL_JARJAR_RULES := $(LOCAL_PATH)/jarjar-rules.txt
-
-LOCAL_NO_STANDARD_LIBRARIES := true
-LOCAL_JAVA_LIBRARIES := core-oj core-libart
-
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk $(LOCAL_PATH)/jarjar-rules.txt
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
-
-# Host-side version of framework-protos
-# ============================================================
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := host-framework-protos
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_PROTOC_OPTIMIZE_TYPE := nano
-LOCAL_SRC_FILES:= $(call all-proto-files-under, src)
-
-LOCAL_NO_STANDARD_LIBRARIES := true
-LOCAL_STATIC_JAVA_LIBRARIES := host-libprotobuf-java-nano
-
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk $(LOCAL_PATH)/jarjar-rules.txt
-
-include $(BUILD_HOST_JAVA_LIBRARY)
\ No newline at end of file
diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto
index 5dd3620..93aa520 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants.proto
@@ -4704,6 +4704,11 @@
// OS: P
AUTOFILL_SAVE_EXPLICITLY_TRIGGERED = 1229;
+ // OPEN: Settings > Network & Internet > Mobile network > Wi-Fi calling
+ // CATEGORY: SETTINGS
+ // OS: P
+ WIFI_CALLING_FOR_SUB = 1230;
+
// Add new aosp constants above this line.
// END OF AOSP CONSTANTS
}
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index f9213aa..622b8423 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -2877,7 +2877,7 @@
// The backend reports that our dataset has been wiped. Note this in
// the event log; the no-success code below will reset the backup
// state as well.
- EventLog.writeEvent(EventLogTags.BACKUP_RESET, mTransport.transportDirName());
+ EventLog.writeEvent(EventLogTags.BACKUP_RESET, transportName);
}
} catch (Exception e) {
Slog.e(TAG, "Error in backup thread", e);
@@ -9781,7 +9781,8 @@
}
Slog.i(TAG, "Initializing (wiping) backup transport storage: " + transportName);
- EventLog.writeEvent(EventLogTags.BACKUP_START, transport.transportDirName());
+ String transportDirName = transport.transportDirName();
+ EventLog.writeEvent(EventLogTags.BACKUP_START, transportDirName);
long startRealtime = SystemClock.elapsedRealtime();
int status = transport.initializeDevice();
@@ -9794,7 +9795,7 @@
Slog.i(TAG, "Device init successful");
int millis = (int) (SystemClock.elapsedRealtime() - startRealtime);
EventLog.writeEvent(EventLogTags.BACKUP_INITIALIZE);
- resetBackupState(new File(mBaseStateDir, transport.transportDirName()));
+ resetBackupState(new File(mBaseStateDir, transportDirName));
EventLog.writeEvent(EventLogTags.BACKUP_SUCCESS, 0, millis);
synchronized (mQueueLock) {
recordInitPendingLocked(false, transportName);
diff --git a/services/backup/java/com/android/server/backup/internal/PerformBackupTask.java b/services/backup/java/com/android/server/backup/internal/PerformBackupTask.java
index 7a8a920e..c0caa557 100644
--- a/services/backup/java/com/android/server/backup/internal/PerformBackupTask.java
+++ b/services/backup/java/com/android/server/backup/internal/PerformBackupTask.java
@@ -339,7 +339,7 @@
// The backend reports that our dataset has been wiped. Note this in
// the event log; the no-success code below will reset the backup
// state as well.
- EventLog.writeEvent(EventLogTags.BACKUP_RESET, mTransport.transportDirName());
+ EventLog.writeEvent(EventLogTags.BACKUP_RESET, transportName);
}
} catch (Exception e) {
Slog.e(TAG, "Error in backup thread", e);
diff --git a/services/backup/java/com/android/server/backup/internal/PerformInitializeTask.java b/services/backup/java/com/android/server/backup/internal/PerformInitializeTask.java
index 939b1ae..690922f 100644
--- a/services/backup/java/com/android/server/backup/internal/PerformInitializeTask.java
+++ b/services/backup/java/com/android/server/backup/internal/PerformInitializeTask.java
@@ -79,7 +79,8 @@
}
Slog.i(TAG, "Initializing (wiping) backup transport storage: " + transportName);
- EventLog.writeEvent(EventLogTags.BACKUP_START, transport.transportDirName());
+ String transportDirName = transport.transportDirName();
+ EventLog.writeEvent(EventLogTags.BACKUP_START, transportDirName);
long startRealtime = SystemClock.elapsedRealtime();
int status = transport.initializeDevice();
@@ -94,7 +95,7 @@
EventLog.writeEvent(EventLogTags.BACKUP_INITIALIZE);
backupManagerService
.resetBackupState(new File(backupManagerService.getBaseStateDir(),
- transport.transportDirName()));
+ transportDirName));
EventLog.writeEvent(EventLogTags.BACKUP_SUCCESS, 0, millis);
synchronized (backupManagerService.getQueueLock()) {
backupManagerService.recordInitPendingLocked(false, transportName);
diff --git a/services/core/java/com/android/server/BatteryService.java b/services/core/java/com/android/server/BatteryService.java
index e7cf041..b824fab 100644
--- a/services/core/java/com/android/server/BatteryService.java
+++ b/services/core/java/com/android/server/BatteryService.java
@@ -43,6 +43,7 @@
import android.hardware.health.V2_0.IHealth;
import android.hardware.health.V2_0.Result;
import android.os.BatteryManager;
+import android.os.BatteryManagerProto;
import android.os.BatteryManagerInternal;
import android.os.BatteryProperty;
import android.os.Binder;
@@ -913,13 +914,13 @@
synchronized (mLock) {
proto.write(BatteryServiceDumpProto.ARE_UPDATES_STOPPED, mUpdatesStopped);
- int batteryPluggedValue = BatteryServiceDumpProto.BATTERY_PLUGGED_NONE;
+ int batteryPluggedValue = BatteryManagerProto.PLUG_TYPE_NONE;
if (mHealthInfo.legacy.chargerAcOnline) {
- batteryPluggedValue = BatteryServiceDumpProto.BATTERY_PLUGGED_AC;
+ batteryPluggedValue = BatteryManagerProto.PLUG_TYPE_AC;
} else if (mHealthInfo.legacy.chargerUsbOnline) {
- batteryPluggedValue = BatteryServiceDumpProto.BATTERY_PLUGGED_USB;
+ batteryPluggedValue = BatteryManagerProto.PLUG_TYPE_USB;
} else if (mHealthInfo.legacy.chargerWirelessOnline) {
- batteryPluggedValue = BatteryServiceDumpProto.BATTERY_PLUGGED_WIRELESS;
+ batteryPluggedValue = BatteryManagerProto.PLUG_TYPE_WIRELESS;
}
proto.write(BatteryServiceDumpProto.PLUGGED, batteryPluggedValue);
proto.write(BatteryServiceDumpProto.MAX_CHARGING_CURRENT, mHealthInfo.legacy.maxChargingCurrent);
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 348c799..d819a33d 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -70,7 +70,6 @@
import android.net.RouteInfo;
import android.net.UidRange;
import android.net.Uri;
-import android.net.metrics.DefaultNetworkEvent;
import android.net.metrics.IpConnectivityLog;
import android.net.metrics.NetworkEvent;
import android.net.util.MultinetworkPolicyTracker;
@@ -127,6 +126,7 @@
import com.android.internal.util.XmlUtils;
import com.android.server.am.BatteryStatsService;
import com.android.server.connectivity.DataConnectionStats;
+import com.android.server.connectivity.IpConnectivityMetrics;
import com.android.server.connectivity.KeepaliveTracker;
import com.android.server.connectivity.LingerMonitor;
import com.android.server.connectivity.MockableSystemProperties;
@@ -2265,7 +2265,7 @@
// Let rematchAllNetworksAndRequests() below record a new default network event
// if there is a fallback. Taken together, the two form a X -> 0, 0 -> Y sequence
// whose timestamps tell how long it takes to recover a default network.
- logDefaultNetworkEvent(null, nai);
+ metricsLogger().defaultNetworkMetrics().logDefaultNetworkEvent(null, nai);
}
notifyIfacesChangedForNetworkStats();
// TODO - we shouldn't send CALLBACK_LOST to requests that can be satisfied
@@ -4995,7 +4995,8 @@
// Notify system services that this network is up.
makeDefault(newNetwork);
// Log 0 -> X and Y -> X default network transitions, where X is the new default.
- logDefaultNetworkEvent(newNetwork, oldDefaultNetwork);
+ metricsLogger().defaultNetworkMetrics().logDefaultNetworkEvent(
+ newNetwork, oldDefaultNetwork);
// Have a new default network, release the transition wakelock in
scheduleReleaseNetworkTransitionWakelock();
}
@@ -5554,25 +5555,10 @@
return ServiceManager.checkService(name) != null;
}
- private void logDefaultNetworkEvent(NetworkAgentInfo newNai, NetworkAgentInfo prevNai) {
- int newNetid = NETID_UNSET;
- int prevNetid = NETID_UNSET;
- int[] transports = new int[0];
- boolean hadIPv4 = false;
- boolean hadIPv6 = false;
-
- if (newNai != null) {
- newNetid = newNai.network.netId;
- transports = newNai.networkCapabilities.getTransportTypes();
- }
- if (prevNai != null) {
- prevNetid = prevNai.network.netId;
- final LinkProperties lp = prevNai.linkProperties;
- hadIPv4 = lp.hasIPv4Address() && lp.hasIPv4DefaultRoute();
- hadIPv6 = lp.hasGlobalIPv6Address() && lp.hasIPv6DefaultRoute();
- }
-
- mMetricsLog.log(new DefaultNetworkEvent(newNetid, transports, prevNetid, hadIPv4, hadIPv6));
+ @VisibleForTesting
+ protected IpConnectivityMetrics.Logger metricsLogger() {
+ return checkNotNull(LocalServices.getService(IpConnectivityMetrics.Logger.class),
+ "no IpConnectivityMetrics service");
}
private void logNetworkEvent(NetworkAgentInfo nai, int evtype) {
diff --git a/services/core/java/com/android/server/am/ActivityDisplay.java b/services/core/java/com/android/server/am/ActivityDisplay.java
index 29073cb..c04ddf8 100644
--- a/services/core/java/com/android/server/am/ActivityDisplay.java
+++ b/services/core/java/com/android/server/am/ActivityDisplay.java
@@ -604,7 +604,7 @@
public void writeToProto(ProtoOutputStream proto, long fieldId) {
final long token = proto.start(fieldId);
- super.writeToProto(proto, CONFIGURATION_CONTAINER);
+ super.writeToProto(proto, CONFIGURATION_CONTAINER, false /* trim */);
proto.write(ID, mDisplayId);
for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = mStacks.get(stackNdx);
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index a513e14..93c0a395 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -23,17 +23,20 @@
import static android.Manifest.permission.INTERNAL_SYSTEM_WINDOW;
import static android.Manifest.permission.MANAGE_ACTIVITY_STACKS;
import static android.Manifest.permission.READ_FRAME_BUFFER;
+import static android.Manifest.permission.REMOVE_TASKS;
import static android.Manifest.permission.START_TASKS_FROM_RECENTS;
import static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
import static android.app.ActivityManager.LOCK_TASK_MODE_NONE;
import static android.app.ActivityManager.RESIZE_MODE_PRESERVE_WINDOW;
import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
+import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.content.pm.PackageManager.FEATURE_ACTIVITIES_ON_SECONDARY_DISPLAYS;
import static android.content.pm.PackageManager.FEATURE_FREEFORM_WINDOW_MANAGEMENT;
import static android.content.pm.PackageManager.FEATURE_LEANBACK_ONLY;
@@ -227,6 +230,8 @@
import android.app.ProfilerInfo;
import android.app.RemoteAction;
import android.app.WaitResult;
+import android.app.WindowConfiguration.ActivityType;
+import android.app.WindowConfiguration.WindowingMode;
import android.app.admin.DevicePolicyManager;
import android.app.assist.AssistContent;
import android.app.assist.AssistStructure;
@@ -668,7 +673,7 @@
/**
* List of intents that were used to start the most recent tasks.
*/
- final RecentTasks mRecentTasks;
+ private final RecentTasks mRecentTasks;
/**
* For addAppTask: cached of the last activity component that was added.
@@ -2033,7 +2038,9 @@
synchronized (ActivityManagerService.this) {
for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
ProcessRecord r = mLruProcesses.get(i);
- if (r.thread != null) {
+ // Don't dispatch to isolated processes as they can't access
+ // ConnectivityManager and don't have network privileges anyway.
+ if (r.thread != null && !r.isolated) {
try {
r.thread.setHttpProxy(host, port, exclList, pacFileUrl);
} catch (RemoteException ex) {
@@ -2767,7 +2774,7 @@
mTaskChangeNotificationController =
new TaskChangeNotificationController(this, mStackSupervisor, mHandler);
mActivityStarter = new ActivityStarter(this);
- mRecentTasks = new RecentTasks(this, mStackSupervisor);
+ mRecentTasks = createRecentTasks();
mStackSupervisor.setRecentTasks(mRecentTasks);
mLockTaskController = new LockTaskController(mContext, mStackSupervisor, mHandler);
@@ -2813,6 +2820,14 @@
return new ActivityStackSupervisor(this, mHandler.getLooper());
}
+ protected RecentTasks createRecentTasks() {
+ return new RecentTasks(this, mStackSupervisor);
+ }
+
+ RecentTasks getRecentTasks() {
+ return mRecentTasks;
+ }
+
public void setSystemServiceManager(SystemServiceManager mgr) {
mSystemServiceManager = mgr;
}
@@ -3148,6 +3163,7 @@
synchronized (this) {
final ActivityStack stack = mStackSupervisor.getStack(stackId);
if (stack == null) {
+ Slog.w(TAG, "setFocusedStack: No stack with id=" + stackId);
return;
}
final ActivityRecord r = stack.topRunningActivityLocked();
@@ -3184,7 +3200,8 @@
/** Sets the task stack listener that gets callbacks when a task stack changes. */
@Override
public void registerTaskStackListener(ITaskStackListener listener) throws RemoteException {
- enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "registerTaskStackListener()");
+ enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS,
+ "registerTaskStackListener()");
mTaskChangeNotificationController.registerTaskStackListener(listener);
}
@@ -3193,7 +3210,8 @@
*/
@Override
public void unregisterTaskStackListener(ITaskStackListener listener) throws RemoteException {
- enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "unregisterTaskStackListener()");
+ enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS,
+ "unregisterTaskStackListener()");
mTaskChangeNotificationController.unregisterTaskStackListener(listener);
}
@@ -4871,12 +4889,9 @@
@Override
public final int startActivityFromRecents(int taskId, Bundle bOptions) {
- if (checkCallingPermission(START_TASKS_FROM_RECENTS) != PackageManager.PERMISSION_GRANTED) {
- String msg = "Permission Denial: startActivityFromRecents called without " +
- START_TASKS_FROM_RECENTS;
- Slog.w(TAG, msg);
- throw new SecurityException(msg);
- }
+ enforceCallerIsRecentsOrHasPermission(START_TASKS_FROM_RECENTS,
+ "startActivityFromRecents()");
+
final long origId = Binder.clearCallingIdentity();
try {
synchronized (this) {
@@ -8328,9 +8343,6 @@
}
}
- /**
- * This can be called with or without the global lock held.
- */
int checkComponentPermission(String permission, int pid, int uid,
int owningUid, boolean exported) {
if (pid == MY_PID) {
@@ -8405,6 +8417,15 @@
}
/**
+ * This can be called with or without the global lock held.
+ */
+ void enforceCallerIsRecentsOrHasPermission(String permission, String func) {
+ if (!mRecentTasks.isCallerRecents(Binder.getCallingUid())) {
+ enforceCallingPermission(permission, func);
+ }
+ }
+
+ /**
* Determine if UID is holding permissions required to access {@link Uri} in
* the given {@link ProviderInfo}. Final permission checking is always done
* in {@link ContentProvider}.
@@ -9770,25 +9791,34 @@
}
@Override
- public List<RunningTaskInfo> getTasks(int maxNum, int flags) {
+ public List<RunningTaskInfo> getTasks(int maxNum) {
+ return getFilteredTasks(maxNum, ACTIVITY_TYPE_UNDEFINED, WINDOWING_MODE_UNDEFINED);
+ }
+
+ @Override
+ public List<RunningTaskInfo> getFilteredTasks(int maxNum, @ActivityType int ignoreActivityType,
+ @WindowingMode int ignoreWindowingMode) {
final int callingUid = Binder.getCallingUid();
- ArrayList<RunningTaskInfo> list = new ArrayList<RunningTaskInfo>();
+ ArrayList<RunningTaskInfo> list = new ArrayList<>();
synchronized(this) {
- if (DEBUG_ALL) Slog.v(
- TAG, "getTasks: max=" + maxNum + ", flags=" + flags);
+ if (DEBUG_ALL) Slog.v(TAG, "getTasks: max=" + maxNum);
final boolean allowed = isGetTasksAllowed("getTasks", Binder.getCallingPid(),
callingUid);
-
- // TODO: Improve with MRU list from all ActivityStacks.
- mStackSupervisor.getTasksLocked(maxNum, list, callingUid, allowed);
+ mStackSupervisor.getRunningTasks(maxNum, list, ignoreActivityType,
+ ignoreWindowingMode, callingUid, allowed);
}
return list;
}
private boolean isGetTasksAllowed(String caller, int callingPid, int callingUid) {
+ if (mRecentTasks.isCallerRecents(callingUid)) {
+ // Always allow the recents component to get tasks
+ return true;
+ }
+
boolean allowed = checkPermission(android.Manifest.permission.REAL_GET_TASKS,
callingPid, callingUid) == PackageManager.PERMISSION_GRANTED;
if (!allowed) {
@@ -9836,8 +9866,7 @@
@Override
public ActivityManager.TaskDescription getTaskDescription(int id) {
synchronized (this) {
- enforceCallingPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS,
- "getTaskDescription()");
+ enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "getTaskDescription()");
final TaskRecord tr = mStackSupervisor.anyTaskForIdLocked(id,
MATCH_TASK_IN_STACKS_OR_RECENT_TASKS);
if (tr != null) {
@@ -10031,7 +10060,8 @@
@Override
public void cancelTaskWindowTransition(int taskId) {
- enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "cancelTaskWindowTransition()");
+ enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS,
+ "cancelTaskWindowTransition()");
final long ident = Binder.clearCallingIdentity();
try {
synchronized (this) {
@@ -10050,7 +10080,8 @@
@Override
public void cancelTaskThumbnailTransition(int taskId) {
- enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "cancelTaskThumbnailTransition()");
+ enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS,
+ "cancelTaskThumbnailTransition()");
final long ident = Binder.clearCallingIdentity();
try {
synchronized (this) {
@@ -10069,7 +10100,7 @@
@Override
public TaskSnapshot getTaskSnapshot(int taskId, boolean reducedResolution) {
- enforceCallingPermission(READ_FRAME_BUFFER, "getTaskSnapshot()");
+ enforceCallerIsRecentsOrHasPermission(READ_FRAME_BUFFER, "getTaskSnapshot()");
final long ident = Binder.clearCallingIdentity();
try {
final TaskRecord task;
@@ -10122,12 +10153,13 @@
@Override
public void removeStack(int stackId) {
- enforceCallingPermission(Manifest.permission.MANAGE_ACTIVITY_STACKS, "removeStack()");
+ enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "removeStack()");
synchronized (this) {
final long ident = Binder.clearCallingIdentity();
try {
final ActivityStack stack = mStackSupervisor.getStack(stackId);
if (stack == null) {
+ Slog.w(TAG, "removeStack: No stack with id=" + stackId);
return;
}
if (!stack.isActivityTypeStandardOrUndefined()) {
@@ -10147,7 +10179,8 @@
*/
@Override
public void removeStacksInWindowingModes(int[] windowingModes) {
- enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "removeStacksInWindowingModes()");
+ enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS,
+ "removeStacksInWindowingModes()");
synchronized (this) {
final long ident = Binder.clearCallingIdentity();
try {
@@ -10160,7 +10193,8 @@
@Override
public void removeStacksWithActivityTypes(int[] activityTypes) {
- enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "removeStacksWithActivityTypes()");
+ enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS,
+ "removeStacksWithActivityTypes()");
synchronized (this) {
final long ident = Binder.clearCallingIdentity();
try {
@@ -10189,7 +10223,7 @@
@Override
public boolean removeTask(int taskId) {
- enforceCallingPermission(android.Manifest.permission.REMOVE_TASKS, "removeTask()");
+ enforceCallerIsRecentsOrHasPermission(REMOVE_TASKS, "removeTask()");
synchronized (this) {
final long ident = Binder.clearCallingIdentity();
try {
@@ -10366,7 +10400,7 @@
@Override
public void setTaskWindowingMode(int taskId, int windowingMode, boolean toTop) {
- enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "setTaskWindowingMode()");
+ enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "setTaskWindowingMode()");
synchronized (this) {
final long ident = Binder.clearCallingIdentity();
try {
@@ -10402,7 +10436,7 @@
@Override
public void moveTaskToStack(int taskId, int stackId, boolean toTop) {
- enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "moveTaskToStack()");
+ enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "moveTaskToStack()");
synchronized (this) {
long ident = Binder.clearCallingIdentity();
try {
@@ -10453,7 +10487,7 @@
@Override
public boolean moveTaskToDockedStack(int taskId, int createMode, boolean toTop, boolean animate,
Rect initialBounds) {
- enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "moveTaskToDockedStack()");
+ enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "moveTaskToDockedStack()");
synchronized (this) {
long ident = Binder.clearCallingIdentity();
try {
@@ -10492,12 +10526,16 @@
*/
@Override
public void dismissSplitScreenMode(boolean toTop) {
- enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "dismissSplitScreenMode()");
+ enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "dismissSplitScreenMode()");
final long ident = Binder.clearCallingIdentity();
try {
synchronized (this) {
final ActivityStack stack =
mStackSupervisor.getDefaultDisplay().getSplitScreenPrimaryStack();
+ if (stack == null) {
+ Slog.w(TAG, "dismissSplitScreenMode: primary split-screen stack not found.");
+ return;
+ }
if (toTop) {
mStackSupervisor.resizeStackLocked(stack, null /* destBounds */,
null /* tempTaskBounds */, null /* tempTaskInsetBounds */,
@@ -10520,14 +10558,14 @@
*/
@Override
public void dismissPip(boolean animate, int animationDuration) {
- enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "dismissPip()");
+ enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "dismissPip()");
final long ident = Binder.clearCallingIdentity();
try {
synchronized (this) {
final PinnedActivityStack stack =
mStackSupervisor.getDefaultDisplay().getPinnedStack();
-
if (stack == null) {
+ Slog.w(TAG, "dismissPip: pinned stack not found.");
return;
}
if (stack.getWindowingMode() != WINDOWING_MODE_PINNED) {
@@ -10557,7 +10595,8 @@
*/
@Override
public boolean moveTopActivityToPinnedStack(int stackId, Rect bounds) {
- enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "moveTopActivityToPinnedStack()");
+ enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS,
+ "moveTopActivityToPinnedStack()");
synchronized (this) {
if (!mSupportsPictureInPicture) {
throw new IllegalStateException("moveTopActivityToPinnedStack:"
@@ -10576,13 +10615,14 @@
@Override
public void resizeStack(int stackId, Rect destBounds, boolean allowResizeInDockedMode,
boolean preserveWindows, boolean animate, int animationDuration) {
- enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "resizeStack()");
+ enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "resizeStack()");
long ident = Binder.clearCallingIdentity();
try {
synchronized (this) {
if (animate) {
final PinnedActivityStack stack = mStackSupervisor.getStack(stackId);
if (stack == null) {
+ Slog.w(TAG, "resizeStack: stackId " + stackId + " not found.");
return;
}
if (stack.getWindowingMode() != WINDOWING_MODE_PINNED) {
@@ -10611,8 +10651,7 @@
public void resizeDockedStack(Rect dockedBounds, Rect tempDockedTaskBounds,
Rect tempDockedTaskInsetBounds,
Rect tempOtherTaskBounds, Rect tempOtherTaskInsetBounds) {
- enforceCallingPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS,
- "resizeDockedStack()");
+ enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "resizeDockedStack()");
long ident = Binder.clearCallingIdentity();
try {
synchronized (this) {
@@ -10627,8 +10666,7 @@
@Override
public void resizePinnedStack(Rect pinnedBounds, Rect tempPinnedTaskBounds) {
- enforceCallingPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS,
- "resizePinnedStack()");
+ enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "resizePinnedStack()");
final long ident = Binder.clearCallingIdentity();
try {
synchronized (this) {
@@ -10687,7 +10725,7 @@
@Override
public List<StackInfo> getAllStackInfos() {
- enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "getAllStackInfos()");
+ enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "getAllStackInfos()");
long ident = Binder.clearCallingIdentity();
try {
synchronized (this) {
@@ -10700,7 +10738,7 @@
@Override
public StackInfo getStackInfo(int windowingMode, int activityType) {
- enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "getStackInfo()");
+ enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "getStackInfo()");
long ident = Binder.clearCallingIdentity();
try {
synchronized (this) {
@@ -11861,8 +11899,7 @@
@Override
public void appNotRespondingViaProvider(IBinder connection) {
- enforceCallingPermission(
- android.Manifest.permission.REMOVE_TASKS, "appNotRespondingViaProvider()");
+ enforceCallingPermission(REMOVE_TASKS, "appNotRespondingViaProvider()");
final ContentProviderConnection conn = (ContentProviderConnection) connection;
if (conn == null) {
@@ -18125,8 +18162,7 @@
// =========================================================
@Override
- public List<ActivityManager.RunningServiceInfo> getServices(int maxNum,
- int flags) {
+ public List<ActivityManager.RunningServiceInfo> getServices(int maxNum, int flags) {
enforceNotIsolatedCaller("getServices");
final int callingUid = Binder.getCallingUid();
@@ -20070,7 +20106,7 @@
@Override
public StackInfo getFocusedStackInfo() throws RemoteException {
- enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "getStackInfo()");
+ enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "getStackInfo()");
long ident = Binder.clearCallingIdentity();
try {
synchronized (this) {
@@ -20110,7 +20146,8 @@
@Override
// TODO: API should just be about changing windowing modes...
public void moveTasksToFullscreenStack(int fromStackId, boolean onTop) {
- enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "moveTasksToFullscreenStack()");
+ enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS,
+ "moveTasksToFullscreenStack()");
synchronized (this) {
final long origId = Binder.clearCallingIdentity();
try {
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index 4cf2794..f942265 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -2305,7 +2305,7 @@
int runWrite(PrintWriter pw) {
mInternal.enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
"registerUidObserver()");
- mInternal.mRecentTasks.flush();
+ mInternal.getRecentTasks().flush();
pw.println("All tasks persisted.");
return 0;
}
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index b47f819..2f0b649 100644
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -204,7 +204,6 @@
private static final String TAG_VISIBILITY = TAG + POSTFIX_VISIBILITY;
private static final boolean SHOW_ACTIVITY_START_TIME = true;
- private static final String RECENTS_PACKAGE_NAME = "com.android.systemui.recents";
private static final String ATTR_ID = "id";
private static final String TAG_INTENT = "intent";
@@ -1058,7 +1057,7 @@
// We only allow home activities to be resizeable if they explicitly requested it.
info.resizeMode = RESIZE_MODE_UNRESIZEABLE;
}
- } else if (realActivity.getClassName().contains(RECENTS_PACKAGE_NAME)) {
+ } else if (service.getRecentTasks().isRecentsComponent(realActivity, appInfo.uid)) {
activityType = ACTIVITY_TYPE_RECENTS;
} else if (options != null && options.getLaunchActivityType() == ACTIVITY_TYPE_ASSISTANT
&& canLaunchAssistActivity(launchedFromPackage)) {
@@ -1562,17 +1561,7 @@
return false;
}
- boolean isVisible = !behindFullscreenActivity || mLaunchTaskBehind;
-
- if (service.mSupportsLeanbackOnly && isVisible && isActivityTypeRecents()) {
- // On devices that support leanback only (Android TV), Recents activity can only be
- // visible if the home stack is the focused stack or we are in split-screen mode.
- final ActivityDisplay display = getDisplay();
- boolean hasSplitScreenStack = display != null && display.hasSplitScreenPrimaryStack();
- isVisible = hasSplitScreenStack || mStackSupervisor.isFocusedStack(getStack());
- }
-
- return isVisible;
+ return !behindFullscreenActivity || mLaunchTaskBehind;
}
void makeVisibleIfNeeded(ActivityRecord starting) {
@@ -2074,7 +2063,7 @@
final File iconFile = new File(TaskPersister.getUserImagesDir(task.userId),
iconFilename);
final String iconFilePath = iconFile.getAbsolutePath();
- service.mRecentTasks.saveImage(icon, iconFilePath);
+ service.getRecentTasks().saveImage(icon, iconFilePath);
_taskDescription.setIconFilename(iconFilePath);
}
taskDescription = _taskDescription;
@@ -2821,7 +2810,7 @@
public void writeToProto(ProtoOutputStream proto, long fieldId) {
final long token = proto.start(fieldId);
- super.writeToProto(proto, CONFIGURATION_CONTAINER);
+ super.writeToProto(proto, CONFIGURATION_CONTAINER, false /* trim */);
writeIdentifierToProto(proto, IDENTIFIER);
proto.write(STATE, state.toString());
proto.write(VISIBLE, visible);
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index bafcce7..ba41bd4 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -99,6 +99,8 @@
import android.app.AppGlobals;
import android.app.IActivityController;
import android.app.ResultInfo;
+import android.app.WindowConfiguration.ActivityType;
+import android.app.WindowConfiguration.WindowingMode;
import android.content.ComponentName;
import android.content.Intent;
import android.content.pm.ActivityInfo;
@@ -4605,69 +4607,43 @@
return didSomething;
}
- void getTasksLocked(List<RunningTaskInfo> list, int callingUid, boolean allowed) {
+ /**
+ * @return The set of running tasks through {@param tasksOut} that are available to the caller.
+ * If {@param ignoreActivityType} or {@param ignoreWindowingMode} are not undefined,
+ * then skip running tasks that match those types.
+ */
+ void getRunningTasks(List<TaskRecord> tasksOut, @ActivityType int ignoreActivityType,
+ @WindowingMode int ignoreWindowingMode, int callingUid, boolean allowed) {
boolean focusedStack = mStackSupervisor.getFocusedStack() == this;
boolean topTask = true;
for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
final TaskRecord task = mTaskHistory.get(taskNdx);
if (task.getTopActivity() == null) {
+ // Skip if there are no activities in the task
continue;
}
- ActivityRecord r = null;
- ActivityRecord top = null;
- ActivityRecord tmp;
- int numActivities = 0;
- int numRunning = 0;
- final ArrayList<ActivityRecord> activities = task.mActivities;
if (!allowed && !task.isActivityTypeHome() && task.effectiveUid != callingUid) {
+ // Skip if the caller can't fetch this task
continue;
}
- for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
- tmp = activities.get(activityNdx);
- if (tmp.finishing) {
- continue;
- }
- r = tmp;
-
- // Initialize state for next task if needed.
- if (top == null || (top.state == ActivityState.INITIALIZING)) {
- top = r;
- numActivities = numRunning = 0;
- }
-
- // Add 'r' into the current task.
- numActivities++;
- if (r.app != null && r.app.thread != null) {
- numRunning++;
- }
-
- if (DEBUG_ALL) Slog.v(
- TAG, r.intent.getComponent().flattenToShortString()
- + ": task=" + r.getTask());
+ if (ignoreActivityType != ACTIVITY_TYPE_UNDEFINED
+ && task.getActivityType() == ignoreActivityType) {
+ // Skip ignored activity type
+ continue;
}
-
- RunningTaskInfo ci = new RunningTaskInfo();
- ci.id = task.taskId;
- ci.stackId = mStackId;
- ci.baseActivity = r.intent.getComponent();
- ci.topActivity = top.intent.getComponent();
- ci.lastActiveTime = task.lastActiveTime;
+ if (ignoreWindowingMode != WINDOWING_MODE_UNDEFINED
+ && task.getWindowingMode() == ignoreWindowingMode) {
+ // Skip ignored windowing mode
+ continue;
+ }
if (focusedStack && topTask) {
- // Give the latest time to ensure foreground task can be sorted
- // at the first, because lastActiveTime of creating task is 0.
- ci.lastActiveTime = SystemClock.elapsedRealtime();
+ // For the focused stack top task, update the last stack active time so that it can
+ // be used to determine the order of the tasks (it may not be set for newly created
+ // tasks)
+ task.lastActiveTime = SystemClock.elapsedRealtime();
topTask = false;
}
-
- if (top.getTask() != null) {
- ci.description = top.getTask().lastDescription;
- }
- ci.numActivities = numActivities;
- ci.numRunning = numRunning;
- ci.supportsSplitScreenMultiWindow = task.supportsSplitScreenWindowingMode();
- ci.resizeMode = task.mResizeMode;
- ci.configuration.setTo(task.getConfiguration());
- list.add(ci);
+ tasksOut.add(task);
}
}
@@ -5023,7 +4999,7 @@
public void writeToProto(ProtoOutputStream proto, long fieldId) {
final long token = proto.start(fieldId);
- super.writeToProto(proto, CONFIGURATION_CONTAINER);
+ super.writeToProto(proto, CONFIGURATION_CONTAINER, false /* trim */);
proto.write(ID, mStackId);
for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
final TaskRecord task = mTaskHistory.get(taskNdx);
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 14c0eea..6ec158e 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -110,6 +110,8 @@
import android.app.ProfilerInfo;
import android.app.ResultInfo;
import android.app.WaitResult;
+import android.app.WindowConfiguration.ActivityType;
+import android.app.WindowConfiguration.WindowingMode;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -279,8 +281,12 @@
final ActivityManagerService mService;
+ /** The historial list of recent tasks including inactive tasks */
RecentTasks mRecentTasks;
+ /** Helper class to abstract out logic for fetching the set of currently running tasks */
+ private RunningTasks mRunningTasks;
+
final ActivityStackSupervisorHandler mHandler;
/** Short cut */
@@ -566,6 +572,7 @@
public ActivityStackSupervisor(ActivityManagerService service, Looper looper) {
mService = service;
mHandler = new ActivityStackSupervisorHandler(looper);
+ mRunningTasks = createRunningTasks();
mActivityMetricsLogger = new ActivityMetricsLogger(this, mService.mContext);
mKeyguardController = new KeyguardController(service, this);
@@ -578,6 +585,11 @@
mRecentTasks.registerCallback(this);
}
+ @VisibleForTesting
+ RunningTasks createRunningTasks() {
+ return new RunningTasks();
+ }
+
/**
* At the time when the constructor runs, the power manager has not yet been
* initialized. So we initialize our wakelocks afterwards.
@@ -1152,43 +1164,12 @@
return null;
}
- void getTasksLocked(int maxNum, List<RunningTaskInfo> list, int callingUid, boolean allowed) {
- // Gather all of the running tasks for each stack into runningTaskLists.
- ArrayList<ArrayList<RunningTaskInfo>> runningTaskLists = new ArrayList<>();
- final int numDisplays = mActivityDisplays.size();
- for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
- final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
- for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = display.getChildAt(stackNdx);
- ArrayList<RunningTaskInfo> stackTaskList = new ArrayList<>();
- runningTaskLists.add(stackTaskList);
- stack.getTasksLocked(stackTaskList, callingUid, allowed);
- }
- }
-
- // The lists are already sorted from most recent to oldest. Just pull the most recent off
- // each list and add it to list. Stop when all lists are empty or maxNum reached.
- while (maxNum > 0) {
- long mostRecentActiveTime = Long.MIN_VALUE;
- ArrayList<RunningTaskInfo> selectedStackList = null;
- final int numTaskLists = runningTaskLists.size();
- for (int stackNdx = 0; stackNdx < numTaskLists; ++stackNdx) {
- ArrayList<RunningTaskInfo> stackTaskList = runningTaskLists.get(stackNdx);
- if (!stackTaskList.isEmpty()) {
- final long lastActiveTime = stackTaskList.get(0).lastActiveTime;
- if (lastActiveTime > mostRecentActiveTime) {
- mostRecentActiveTime = lastActiveTime;
- selectedStackList = stackTaskList;
- }
- }
- }
- if (selectedStackList != null) {
- list.add(selectedStackList.remove(0));
- --maxNum;
- } else {
- break;
- }
- }
+ @VisibleForTesting
+ void getRunningTasks(int maxNum, List<RunningTaskInfo> list,
+ @ActivityType int ignoreActivityType, @WindowingMode int ignoreWindowingMode,
+ int callingUid, boolean allowed) {
+ mRunningTasks.getTasks(maxNum, list, ignoreActivityType, ignoreWindowingMode,
+ mActivityDisplays, callingUid, allowed);
}
ActivityInfo resolveActivity(Intent intent, ResolveInfo rInfo, int startFlags,
@@ -1584,7 +1565,10 @@
return false;
}
if (options != null) {
- if (options.getLaunchTaskId() != INVALID_STACK_ID) {
+ // If a launch task id is specified, then ensure that the caller is the recents
+ // component or has the START_TASKS_FROM_RECENTS permission
+ if (options.getLaunchTaskId() != INVALID_TASK_ID
+ && !mRecentTasks.isCallerRecents(callingUid)) {
final int startInTaskPerm = mService.checkPermission(START_TASKS_FROM_RECENTS,
callingPid, callingUid);
if (startInTaskPerm == PERMISSION_DENIED) {
@@ -3692,7 +3676,7 @@
}
public void writeToProto(ProtoOutputStream proto) {
- super.writeToProto(proto, CONFIGURATION_CONTAINER);
+ super.writeToProto(proto, CONFIGURATION_CONTAINER, false /* trim */);
for (int displayNdx = 0; displayNdx < mActivityDisplays.size(); ++displayNdx) {
ActivityDisplay activityDisplay = mActivityDisplays.valueAt(displayNdx);
activityDisplay.writeToProto(proto, DISPLAYS);
diff --git a/services/core/java/com/android/server/am/AppTaskImpl.java b/services/core/java/com/android/server/am/AppTaskImpl.java
index 38b3039..17626ea 100644
--- a/services/core/java/com/android/server/am/AppTaskImpl.java
+++ b/services/core/java/com/android/server/am/AppTaskImpl.java
@@ -82,7 +82,7 @@
if (tr == null) {
throw new IllegalArgumentException("Unable to find task ID " + mTaskId);
}
- return RecentTasks.createRecentTaskInfo(tr);
+ return mService.getRecentTasks().createRecentTaskInfo(tr);
} finally {
Binder.restoreCallingIdentity(origId);
}
diff --git a/services/core/java/com/android/server/am/RecentTasks.java b/services/core/java/com/android/server/am/RecentTasks.java
index ed3f503..0b9e0a2 100644
--- a/services/core/java/com/android/server/am/RecentTasks.java
+++ b/services/core/java/com/android/server/am/RecentTasks.java
@@ -37,8 +37,6 @@
import static com.android.server.am.ActivityStackSupervisor.REMOVE_FROM_RECENTS;
import static com.android.server.am.TaskRecord.INVALID_TASK_ID;
-import com.google.android.collect.Sets;
-
import android.app.ActivityManager;
import android.app.AppGlobals;
import android.content.ComponentName;
@@ -58,15 +56,16 @@
import android.os.RemoteException;
import android.os.SystemProperties;
import android.os.UserHandle;
+import android.text.TextUtils;
import android.util.ArraySet;
-import android.util.MutableBoolean;
-import android.util.MutableInt;
import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.server.am.ActivityStack.ActivityState;
+import com.android.server.am.TaskRecord.TaskActivitiesReport;
+
+import com.google.android.collect.Sets;
import java.io.File;
import java.io.PrintWriter;
@@ -75,7 +74,6 @@
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
-import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.TimeUnit;
@@ -126,6 +124,13 @@
private final UserController mUserController;
/**
+ * Keeps track of the static recents package/component which is granted additional permissions
+ * to call recents-related APIs.
+ */
+ private int mRecentsUid = -1;
+ private ComponentName mRecentsComponent = null;
+
+ /**
* Mapping of user id -> whether recent tasks have been loaded for that user.
*/
private final SparseBooleanArray mUsersWithRecentsLoaded = new SparseBooleanArray(
@@ -154,6 +159,7 @@
private final HashMap<ComponentName, ActivityInfo> mTmpAvailActCache = new HashMap<>();
private final HashMap<String, ApplicationInfo> mTmpAvailAppCache = new HashMap<>();
private final SparseBooleanArray mTmpQuietProfileUserIds = new SparseBooleanArray();
+ private final TaskActivitiesReport mTmpReport = new TaskActivitiesReport();
@VisibleForTesting
RecentTasks(ActivityManagerService service, TaskPersister taskPersister,
@@ -173,7 +179,7 @@
mTaskPersister = new TaskPersister(systemDir, stackSupervisor, service, this);
mGlobalMaxNumTasks = ActivityManager.getMaxRecentTasksStatic();
mHasVisibleRecentTasks = res.getBoolean(com.android.internal.R.bool.config_hasRecents);
- loadParametersFromResources(service.mContext.getResources());
+ loadParametersFromResources(res);
}
@VisibleForTesting
@@ -217,6 +223,47 @@
: -1;
}
+ /**
+ * Loads the static recents component. This is called after the system is ready, but before
+ * any dependent services (like SystemUI) is started.
+ */
+ void loadRecentsComponent(Resources res) {
+ final String rawRecentsComponent = res.getString(
+ com.android.internal.R.string.config_recentsComponentName);
+ if (TextUtils.isEmpty(rawRecentsComponent)) {
+ return;
+ }
+
+ final ComponentName cn = ComponentName.unflattenFromString(rawRecentsComponent);
+ if (cn != null) {
+ try {
+ final ApplicationInfo appInfo = AppGlobals.getPackageManager()
+ .getApplicationInfo(cn.getPackageName(), 0, mService.mContext.getUserId());
+ if (appInfo != null) {
+ mRecentsUid = appInfo.uid;
+ mRecentsComponent = cn;
+ }
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Could not load application info for recents component: " + cn);
+ }
+ }
+ }
+
+ /**
+ * @return whether the current caller has the same uid as the recents component.
+ */
+ boolean isCallerRecents(int callingUid) {
+ return UserHandle.isSameApp(callingUid, mRecentsUid);
+ }
+
+ /**
+ * @return whether the given component is the recents component and shares the same uid as the
+ * recents component.
+ */
+ boolean isRecentsComponent(ComponentName cn, int uid) {
+ return cn.equals(mRecentsComponent) && UserHandle.isSameApp(uid, mRecentsUid);
+ }
+
void registerCallback(Callbacks callback) {
mCallbacks.add(callback);
}
@@ -339,6 +386,7 @@
}
void onSystemReadyLocked() {
+ loadRecentsComponent(mService.mContext.getResources());
mTasks.clear();
mTaskPersister.startPersisting();
}
@@ -690,7 +738,7 @@
continue;
}
- ActivityManager.RecentTaskInfo rti = RecentTasks.createRecentTaskInfo(tr);
+ final ActivityManager.RecentTaskInfo rti = createRecentTaskInfo(tr);
if (!getDetailedTasks) {
rti.baseIntent.replaceExtras((Bundle)null);
}
@@ -1327,12 +1375,14 @@
void dump(PrintWriter pw, boolean dumpAll, String dumpPackage) {
pw.println("ACTIVITY MANAGER RECENT TASKS (dumpsys activity recents)");
+ pw.println("mRecentsUid=" + mRecentsUid);
+ pw.println("mRecentsComponent=" + mRecentsComponent);
if (mTasks.isEmpty()) {
return;
}
- final MutableBoolean printedAnything = new MutableBoolean(false);
- final MutableBoolean printedHeader = new MutableBoolean(false);
+ boolean printedAnything = false;
+ boolean printedHeader = false;
final int size = mTasks.size();
for (int i = 0; i < size; i++) {
final TaskRecord tr = mTasks.get(i);
@@ -1341,10 +1391,10 @@
continue;
}
- if (!printedHeader.value) {
+ if (!printedHeader) {
pw.println(" Recent tasks:");
- printedHeader.value = true;
- printedAnything.value = true;
+ printedHeader = true;
+ printedAnything = true;
}
pw.print(" * Recent #"); pw.print(i); pw.print(": ");
pw.println(tr);
@@ -1353,7 +1403,7 @@
}
}
- if (!printedAnything.value) {
+ if (!printedAnything) {
pw.println(" (nothing)");
}
}
@@ -1361,7 +1411,7 @@
/**
* Creates a new RecentTaskInfo from a TaskRecord.
*/
- static ActivityManager.RecentTaskInfo createRecentTaskInfo(TaskRecord tr) {
+ ActivityManager.RecentTaskInfo createRecentTaskInfo(TaskRecord tr) {
// Update the task description to reflect any changes in the task stack
tr.updateTaskDescription();
@@ -1387,24 +1437,10 @@
rti.resizeMode = tr.mResizeMode;
rti.configuration.setTo(tr.getConfiguration());
- ActivityRecord base = null;
- ActivityRecord top = null;
- ActivityRecord tmp;
-
- for (int i = tr.mActivities.size() - 1; i >= 0; --i) {
- tmp = tr.mActivities.get(i);
- if (tmp.finishing) {
- continue;
- }
- base = tmp;
- if (top == null || (top.state == ActivityState.INITIALIZING)) {
- top = base;
- }
- rti.numActivities++;
- }
-
- rti.baseActivity = (base != null) ? base.intent.getComponent() : null;
- rti.topActivity = (top != null) ? top.intent.getComponent() : null;
+ tr.getNumRunningActivities(mTmpReport);
+ rti.numActivities = mTmpReport.numActivities;
+ rti.baseActivity = (mTmpReport.base != null) ? mTmpReport.base.intent.getComponent() : null;
+ rti.topActivity = (mTmpReport.top != null) ? mTmpReport.top.intent.getComponent() : null;
return rti;
}
diff --git a/services/core/java/com/android/server/am/RunningTasks.java b/services/core/java/com/android/server/am/RunningTasks.java
new file mode 100644
index 0000000..400b03a
--- /dev/null
+++ b/services/core/java/com/android/server/am/RunningTasks.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2017 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.am;
+
+import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
+import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
+
+import android.app.ActivityManager.RunningTaskInfo;
+import android.app.WindowConfiguration.ActivityType;
+import android.app.WindowConfiguration.WindowingMode;
+import android.util.SparseArray;
+
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.List;
+import java.util.TreeSet;
+
+/**
+ * Class for resolving the set of running tasks in the system.
+ */
+class RunningTasks {
+
+ // Comparator to sort by last active time (descending)
+ private static final Comparator<TaskRecord> LAST_ACTIVE_TIME_COMPARATOR =
+ (o1, o2) -> Long.signum(o2.lastActiveTime - o1.lastActiveTime);
+
+ private final TaskRecord.TaskActivitiesReport mTmpReport =
+ new TaskRecord.TaskActivitiesReport();
+ private final TreeSet<TaskRecord> mTmpSortedSet = new TreeSet<>(LAST_ACTIVE_TIME_COMPARATOR);
+ private final ArrayList<TaskRecord> mTmpStackTasks = new ArrayList<>();
+
+ void getTasks(int maxNum, List<RunningTaskInfo> list, @ActivityType int ignoreActivityType,
+ @WindowingMode int ignoreWindowingMode, SparseArray<ActivityDisplay> activityDisplays,
+ int callingUid, boolean allowed) {
+ // For each stack on each display, add the tasks into the sorted set and then pull the first
+ // {@param maxNum} from the set
+
+ // Gather all of the tasks across all of the tasks, and add them to the sorted set
+ mTmpSortedSet.clear();
+ mTmpStackTasks.clear();
+ final int numDisplays = activityDisplays.size();
+ for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
+ final ActivityDisplay display = activityDisplays.valueAt(displayNdx);
+ for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getChildAt(stackNdx);
+ stack.getRunningTasks(mTmpStackTasks, ignoreActivityType, ignoreWindowingMode,
+ callingUid, allowed);
+ for (int i = mTmpStackTasks.size() - 1; i >= 0; i--) {
+ mTmpSortedSet.addAll(mTmpStackTasks);
+ }
+ }
+ }
+
+ // Take the first {@param maxNum} tasks and create running task infos for them
+ final Iterator<TaskRecord> iter = mTmpSortedSet.iterator();
+ while (iter.hasNext()) {
+ if (maxNum == 0) {
+ break;
+ }
+
+ final TaskRecord task = iter.next();
+ list.add(createRunningTaskInfo(task));
+ maxNum--;
+ }
+ }
+
+ /**
+ * Constructs a {@link RunningTaskInfo} from a given {@param task}.
+ */
+ private RunningTaskInfo createRunningTaskInfo(TaskRecord task) {
+ task.getNumRunningActivities(mTmpReport);
+
+ final RunningTaskInfo ci = new RunningTaskInfo();
+ ci.id = task.taskId;
+ ci.stackId = task.getStackId();
+ ci.baseActivity = mTmpReport.base.intent.getComponent();
+ ci.topActivity = mTmpReport.top.intent.getComponent();
+ ci.lastActiveTime = task.lastActiveTime;
+ ci.description = task.lastDescription;
+ ci.numActivities = mTmpReport.numActivities;
+ ci.numRunning = mTmpReport.numRunning;
+ ci.supportsSplitScreenMultiWindow = task.supportsSplitScreenWindowingMode();
+ ci.resizeMode = task.mResizeMode;
+ ci.configuration.setTo(task.getConfiguration());
+ return ci;
+ }
+}
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index f04bdb3..1b5a1ce 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -112,6 +112,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.IVoiceInteractor;
import com.android.internal.util.XmlUtils;
+import com.android.server.am.ActivityStack.ActivityState;
import com.android.server.wm.AppWindowContainerController;
import com.android.server.wm.ConfigurationContainer;
import com.android.server.wm.StackWindowController;
@@ -1060,6 +1061,36 @@
return null;
}
+ /**
+ * Return the number of running activities, and the number of non-finishing/initializing
+ * activities in the provided {@param reportOut} respectively.
+ */
+ void getNumRunningActivities(TaskActivitiesReport reportOut) {
+ reportOut.reset();
+ for (int i = mActivities.size() - 1; i >= 0; --i) {
+ final ActivityRecord r = mActivities.get(i);
+ if (r.finishing) {
+ continue;
+ }
+
+ reportOut.base = r;
+
+ // Increment the total number of non-finishing activities
+ reportOut.numActivities++;
+
+ if (reportOut.top == null || (reportOut.top.state == ActivityState.INITIALIZING)) {
+ reportOut.top = r;
+ // Reset the number of running activities until we hit the first non-initializing
+ // activity
+ reportOut.numRunning = 0;
+ }
+ if (r.app != null && r.app.thread != null) {
+ // Increment the number of actually running activities
+ reportOut.numRunning++;
+ }
+ }
+ }
+
boolean okToShowLocked() {
// NOTE: If {@link TaskRecord#topRunningActivityLocked} return is not null then it is
// okay to show the activity when locked.
@@ -2205,7 +2236,7 @@
public void writeToProto(ProtoOutputStream proto, long fieldId) {
final long token = proto.start(fieldId);
- super.writeToProto(proto, CONFIGURATION_CONTAINER);
+ super.writeToProto(proto, CONFIGURATION_CONTAINER, false /* trim */);
proto.write(ID, taskId);
for (int i = mActivities.size() - 1; i >= 0; i--) {
ActivityRecord activity = mActivities.get(i);
@@ -2231,4 +2262,19 @@
proto.write(MIN_HEIGHT, mMinHeight);
proto.end(token);
}
+
+ /**
+ * See {@link #getNumRunningActivities(TaskActivitiesReport)}.
+ */
+ static class TaskActivitiesReport {
+ int numRunning;
+ int numActivities;
+ ActivityRecord top;
+ ActivityRecord base;
+
+ void reset() {
+ numRunning = numActivities = 0;
+ top = base = null;
+ }
+ }
}
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index 4aa8adb9..1b42818 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -250,21 +250,21 @@
}
void stopRunningUsersLU(int maxRunningUsers) {
- int num = mUserLru.size();
+ int currentlyRunning = mUserLru.size();
int i = 0;
- while (num > maxRunningUsers && i < mUserLru.size()) {
+ while (currentlyRunning > maxRunningUsers && i < mUserLru.size()) {
Integer oldUserId = mUserLru.get(i);
UserState oldUss = mStartedUsers.get(oldUserId);
if (oldUss == null) {
// Shouldn't happen, but be sane if it does.
mUserLru.remove(i);
- num--;
+ currentlyRunning--;
continue;
}
if (oldUss.state == UserState.STATE_STOPPING
|| oldUss.state == UserState.STATE_SHUTDOWN) {
// This user is already stopping, doesn't count.
- num--;
+ currentlyRunning--;
i++;
continue;
}
@@ -272,16 +272,15 @@
// Owner/System user and current user can't be stopped. We count it as running
// when it is not a pure system user.
if (UserInfo.isSystemOnly(oldUserId)) {
- num--;
+ currentlyRunning--;
}
i++;
continue;
}
// This is a user to be stopped.
- if (stopUsersLU(oldUserId, false, null) != USER_OP_SUCCESS) {
- num--;
+ if (stopUsersLU(oldUserId, false, null) == USER_OP_SUCCESS) {
+ currentlyRunning--;
}
- num--;
i++;
}
}
@@ -2021,7 +2020,7 @@
void loadUserRecents(int userId) {
synchronized (mService) {
- mService.mRecentTasks.loadUserRecentsLocked(userId);
+ mService.getRecentTasks().loadUserRecentsLocked(userId);
}
}
diff --git a/services/core/java/com/android/server/connectivity/DefaultNetworkMetrics.java b/services/core/java/com/android/server/connectivity/DefaultNetworkMetrics.java
new file mode 100644
index 0000000..8981db1
--- /dev/null
+++ b/services/core/java/com/android/server/connectivity/DefaultNetworkMetrics.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2017 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.connectivity;
+
+import android.net.LinkProperties;
+import android.net.metrics.DefaultNetworkEvent;
+import android.net.metrics.IpConnectivityLog;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.IpConnectivityEvent;
+
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Tracks events related to the default network for the purpose of default network metrics.
+ * {@hide}
+ */
+public class DefaultNetworkMetrics {
+
+ private static final int ROLLING_LOG_SIZE = 64;
+
+ // Event buffer used for metrics upload. The buffer is cleared when events are collected.
+ @GuardedBy("this")
+ private final List<DefaultNetworkEvent> mEvents = new ArrayList<>();
+
+ public synchronized void listEvents(PrintWriter pw) {
+ long localTimeMs = System.currentTimeMillis();
+ for (DefaultNetworkEvent ev : mEvents) {
+ pw.println(ev);
+ }
+ }
+
+ public synchronized void listEventsAsProto(PrintWriter pw) {
+ for (DefaultNetworkEvent ev : mEvents) {
+ pw.print(IpConnectivityEventBuilder.toProto(ev));
+ }
+ }
+
+ public synchronized void flushEvents(List<IpConnectivityEvent> out) {
+ for (DefaultNetworkEvent ev : mEvents) {
+ out.add(IpConnectivityEventBuilder.toProto(ev));
+ }
+ mEvents.clear();
+ }
+
+ public synchronized void logDefaultNetworkEvent(
+ NetworkAgentInfo newNai, NetworkAgentInfo prevNai) {
+ DefaultNetworkEvent ev = new DefaultNetworkEvent();
+ if (newNai != null) {
+ ev.netId = newNai.network().netId;
+ ev.transportTypes = newNai.networkCapabilities.getTransportTypes();
+ }
+ if (prevNai != null) {
+ ev.prevNetId = prevNai.network().netId;
+ final LinkProperties lp = prevNai.linkProperties;
+ ev.prevIPv4 = lp.hasIPv4Address() && lp.hasIPv4DefaultRoute();
+ ev.prevIPv6 = lp.hasGlobalIPv6Address() && lp.hasIPv6DefaultRoute();
+ }
+
+ mEvents.add(ev);
+ }
+}
diff --git a/services/core/java/com/android/server/connectivity/IpConnectivityEventBuilder.java b/services/core/java/com/android/server/connectivity/IpConnectivityEventBuilder.java
index 67e7216..3d71ecb 100644
--- a/services/core/java/com/android/server/connectivity/IpConnectivityEventBuilder.java
+++ b/services/core/java/com/android/server/connectivity/IpConnectivityEventBuilder.java
@@ -132,6 +132,18 @@
return out;
}
+ public static IpConnectivityEvent toProto(DefaultNetworkEvent in) {
+ IpConnectivityLogClass.DefaultNetworkEvent ev =
+ new IpConnectivityLogClass.DefaultNetworkEvent();
+ ev.networkId = netIdOf(in.netId);
+ ev.previousNetworkId = netIdOf(in.prevNetId);
+ ev.transportTypes = in.transportTypes;
+ ev.previousNetworkIpSupport = ipSupportOf(in);
+ final IpConnectivityEvent out = buildEvent(in.netId, 0, null);
+ out.setDefaultNetworkEvent(ev);
+ return out;
+ }
+
private static IpConnectivityEvent buildEvent(int netId, long transports, String ifname) {
final IpConnectivityEvent ev = new IpConnectivityEvent();
ev.networkId = netId;
@@ -164,11 +176,6 @@
return true;
}
- if (in instanceof DefaultNetworkEvent) {
- setDefaultNetworkEvent(out, (DefaultNetworkEvent) in);
- return true;
- }
-
if (in instanceof NetworkEvent) {
setNetworkEvent(out, (NetworkEvent) in);
return true;
@@ -225,16 +232,6 @@
out.setIpReachabilityEvent(ipReachabilityEvent);
}
- private static void setDefaultNetworkEvent(IpConnectivityEvent out, DefaultNetworkEvent in) {
- IpConnectivityLogClass.DefaultNetworkEvent defaultNetworkEvent =
- new IpConnectivityLogClass.DefaultNetworkEvent();
- defaultNetworkEvent.networkId = netIdOf(in.netId);
- defaultNetworkEvent.previousNetworkId = netIdOf(in.prevNetId);
- defaultNetworkEvent.transportTypes = in.transportTypes;
- defaultNetworkEvent.previousNetworkIpSupport = ipSupportOf(in);
- out.setDefaultNetworkEvent(defaultNetworkEvent);
- }
-
private static void setNetworkEvent(IpConnectivityEvent out, NetworkEvent in) {
IpConnectivityLogClass.NetworkEvent networkEvent =
new IpConnectivityLogClass.NetworkEvent();
diff --git a/services/core/java/com/android/server/connectivity/IpConnectivityMetrics.java b/services/core/java/com/android/server/connectivity/IpConnectivityMetrics.java
index f2445fa..24217e6 100644
--- a/services/core/java/com/android/server/connectivity/IpConnectivityMetrics.java
+++ b/services/core/java/com/android/server/connectivity/IpConnectivityMetrics.java
@@ -32,12 +32,15 @@
import android.util.ArrayMap;
import android.util.Base64;
import android.util.Log;
+
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.RingBuffer;
import com.android.internal.util.TokenBucket;
+import com.android.server.LocalServices;
import com.android.server.SystemService;
import com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.IpConnectivityEvent;
+
import java.io.FileDescriptor;
import java.io.IOException;
import java.io.PrintWriter;
@@ -112,6 +115,9 @@
private final ToIntFunction<Context> mCapacityGetter;
+ @VisibleForTesting
+ final DefaultNetworkMetrics mDefaultNetworkMetrics = new DefaultNetworkMetrics();
+
public IpConnectivityMetrics(Context ctx, ToIntFunction<Context> capacityGetter) {
super(ctx);
mCapacityGetter = capacityGetter;
@@ -135,6 +141,8 @@
publishBinderService(SERVICE_NAME, impl);
publishBinderService(mNetdListener.SERVICE_NAME, mNetdListener);
+
+ LocalServices.addService(Logger.class, new LoggerImpl());
}
}
@@ -188,6 +196,8 @@
final List<IpConnectivityEvent> protoEvents = IpConnectivityEventBuilder.toProto(events);
+ mDefaultNetworkMetrics.flushEvents(protoEvents);
+
if (mNetdListener != null) {
mNetdListener.flushStatistics(protoEvents);
}
@@ -228,6 +238,7 @@
if (mNetdListener != null) {
mNetdListener.listAsProtos(pw);
}
+ mDefaultNetworkMetrics.listEventsAsProto(pw);
return;
}
@@ -237,6 +248,7 @@
if (mNetdListener != null) {
mNetdListener.list(pw);
}
+ mDefaultNetworkMetrics.listEvents(pw);
}
/**
@@ -254,6 +266,7 @@
if (mNetdListener != null) {
mNetdListener.list(pw);
}
+ mDefaultNetworkMetrics.listEvents(pw);
}
private void cmdStats(FileDescriptor fd, PrintWriter pw, String[] args) {
@@ -366,4 +379,15 @@
map.put(ApfProgramEvent.class, new TokenBucket((int)DateUtils.MINUTE_IN_MILLIS, 50));
return map;
}
+
+ /** Direct non-Binder interface for event producer clients within the system servers. */
+ public interface Logger {
+ DefaultNetworkMetrics defaultNetworkMetrics();
+ }
+
+ private class LoggerImpl implements Logger {
+ public DefaultNetworkMetrics defaultNetworkMetrics() {
+ return mDefaultNetworkMetrics;
+ }
+ }
}
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
index a4a8e6f..40a02b9 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -288,7 +288,21 @@
final String[] packages = mContext.getPackageManager().getPackagesForUid(uid);
if (packages != null && packages.length > 0) {
- final PackageParser.Package pkg = mPackageManagerInt.getPackage(packages[0]);
+Slog.e(TAG, "TODD: Packages: " + Arrays.toString(packages));
+ PackageParser.Package pkg = null;
+ for (String packageName : packages) {
+ pkg = mPackageManagerInt.getPackage(packageName);
+ if (pkg != null) {
+Slog.e(TAG, "TODD: Using packge: " + packageName);
+ break;
+ } else {
+Slog.e(TAG, "TODD: Missing packge: " + packageName);
+ }
+ }
+ if (pkg == null) {
+Slog.e(TAG, "TODD: No package not found; UID: " + uid);
+ return PackageManager.PERMISSION_DENIED;
+ }
if (pkg.mSharedUserId != null) {
if (isCallerInstantApp) {
return PackageManager.PERMISSION_DENIED;
@@ -1058,7 +1072,7 @@
// before. In this case we do want to allow the app to
// now get the new permission if the ancestral apk is
// privileged to get it.
- if (disabledPkg != null
+ if (disabledPs != null && disabledPkg != null
&& isPackageRequestingPermission(disabledPkg, perm)
&& ((privilegedPermission && disabledPs.isPrivileged())
|| (oemPermission && disabledPs.isOem()
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index b917dae..2494bde 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -58,10 +58,6 @@
import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException;
import android.service.dreams.DreamManagerInternal;
-import android.service.power.PowerServiceDumpProto;
-import android.service.power.PowerServiceSettingsAndConfigurationDumpProto;
-import android.service.power.SuspendBlockerProto;
-import android.service.power.WakeLockProto;
import android.service.vr.IVrManager;
import android.service.vr.IVrStateCallbacks;
import android.util.EventLog;
@@ -620,8 +616,8 @@
}
void dumpProto(ProtoOutputStream proto) {
- final long constantsToken = proto.start(PowerServiceDumpProto.CONSTANTS);
- proto.write(PowerServiceDumpProto.ConstantsProto.IS_NO_CACHED_WAKE_LOCKS,
+ final long constantsToken = proto.start(PowerManagerServiceDumpProto.CONSTANTS);
+ proto.write(PowerManagerServiceDumpProto.ConstantsProto.IS_NO_CACHED_WAKE_LOCKS,
NO_CACHED_WAKE_LOCKS);
proto.end(constantsToken);
}
@@ -3396,112 +3392,112 @@
synchronized (mLock) {
mConstants.dumpProto(proto);
- proto.write(PowerServiceDumpProto.DIRTY, mDirty);
- proto.write(PowerServiceDumpProto.WAKEFULNESS, mWakefulness);
- proto.write(PowerServiceDumpProto.IS_WAKEFULNESS_CHANGING, mWakefulnessChanging);
- proto.write(PowerServiceDumpProto.IS_POWERED, mIsPowered);
- proto.write(PowerServiceDumpProto.PLUG_TYPE, mPlugType);
- proto.write(PowerServiceDumpProto.BATTERY_LEVEL, mBatteryLevel);
+ proto.write(PowerManagerServiceDumpProto.DIRTY, mDirty);
+ proto.write(PowerManagerServiceDumpProto.WAKEFULNESS, mWakefulness);
+ proto.write(PowerManagerServiceDumpProto.IS_WAKEFULNESS_CHANGING, mWakefulnessChanging);
+ proto.write(PowerManagerServiceDumpProto.IS_POWERED, mIsPowered);
+ proto.write(PowerManagerServiceDumpProto.PLUG_TYPE, mPlugType);
+ proto.write(PowerManagerServiceDumpProto.BATTERY_LEVEL, mBatteryLevel);
proto.write(
- PowerServiceDumpProto.BATTERY_LEVEL_WHEN_DREAM_STARTED,
+ PowerManagerServiceDumpProto.BATTERY_LEVEL_WHEN_DREAM_STARTED,
mBatteryLevelWhenDreamStarted);
- proto.write(PowerServiceDumpProto.DOCK_STATE, mDockState);
- proto.write(PowerServiceDumpProto.IS_STAY_ON, mStayOn);
- proto.write(PowerServiceDumpProto.IS_PROXIMITY_POSITIVE, mProximityPositive);
- proto.write(PowerServiceDumpProto.IS_BOOT_COMPLETED, mBootCompleted);
- proto.write(PowerServiceDumpProto.IS_SYSTEM_READY, mSystemReady);
+ proto.write(PowerManagerServiceDumpProto.DOCK_STATE, mDockState);
+ proto.write(PowerManagerServiceDumpProto.IS_STAY_ON, mStayOn);
+ proto.write(PowerManagerServiceDumpProto.IS_PROXIMITY_POSITIVE, mProximityPositive);
+ proto.write(PowerManagerServiceDumpProto.IS_BOOT_COMPLETED, mBootCompleted);
+ proto.write(PowerManagerServiceDumpProto.IS_SYSTEM_READY, mSystemReady);
proto.write(
- PowerServiceDumpProto.IS_HAL_AUTO_SUSPEND_MODE_ENABLED,
+ PowerManagerServiceDumpProto.IS_HAL_AUTO_SUSPEND_MODE_ENABLED,
mHalAutoSuspendModeEnabled);
proto.write(
- PowerServiceDumpProto.IS_HAL_AUTO_INTERACTIVE_MODE_ENABLED,
+ PowerManagerServiceDumpProto.IS_HAL_AUTO_INTERACTIVE_MODE_ENABLED,
mHalInteractiveModeEnabled);
- final long activeWakeLocksToken = proto.start(PowerServiceDumpProto.ACTIVE_WAKE_LOCKS);
+ final long activeWakeLocksToken = proto.start(PowerManagerServiceDumpProto.ACTIVE_WAKE_LOCKS);
proto.write(
- PowerServiceDumpProto.ActiveWakeLocksProto.IS_CPU,
+ PowerManagerServiceDumpProto.ActiveWakeLocksProto.IS_CPU,
(mWakeLockSummary & WAKE_LOCK_CPU) != 0);
proto.write(
- PowerServiceDumpProto.ActiveWakeLocksProto.IS_SCREEN_BRIGHT,
+ PowerManagerServiceDumpProto.ActiveWakeLocksProto.IS_SCREEN_BRIGHT,
(mWakeLockSummary & WAKE_LOCK_SCREEN_BRIGHT) != 0);
proto.write(
- PowerServiceDumpProto.ActiveWakeLocksProto.IS_SCREEN_DIM,
+ PowerManagerServiceDumpProto.ActiveWakeLocksProto.IS_SCREEN_DIM,
(mWakeLockSummary & WAKE_LOCK_SCREEN_DIM) != 0);
proto.write(
- PowerServiceDumpProto.ActiveWakeLocksProto.IS_BUTTON_BRIGHT,
+ PowerManagerServiceDumpProto.ActiveWakeLocksProto.IS_BUTTON_BRIGHT,
(mWakeLockSummary & WAKE_LOCK_BUTTON_BRIGHT) != 0);
proto.write(
- PowerServiceDumpProto.ActiveWakeLocksProto.IS_PROXIMITY_SCREEN_OFF,
+ PowerManagerServiceDumpProto.ActiveWakeLocksProto.IS_PROXIMITY_SCREEN_OFF,
(mWakeLockSummary & WAKE_LOCK_PROXIMITY_SCREEN_OFF) != 0);
proto.write(
- PowerServiceDumpProto.ActiveWakeLocksProto.IS_STAY_AWAKE,
+ PowerManagerServiceDumpProto.ActiveWakeLocksProto.IS_STAY_AWAKE,
(mWakeLockSummary & WAKE_LOCK_STAY_AWAKE) != 0);
proto.write(
- PowerServiceDumpProto.ActiveWakeLocksProto.IS_DOZE,
+ PowerManagerServiceDumpProto.ActiveWakeLocksProto.IS_DOZE,
(mWakeLockSummary & WAKE_LOCK_DOZE) != 0);
proto.write(
- PowerServiceDumpProto.ActiveWakeLocksProto.IS_DRAW,
+ PowerManagerServiceDumpProto.ActiveWakeLocksProto.IS_DRAW,
(mWakeLockSummary & WAKE_LOCK_DRAW) != 0);
proto.end(activeWakeLocksToken);
- proto.write(PowerServiceDumpProto.NOTIFY_LONG_SCHEDULED_MS, mNotifyLongScheduled);
- proto.write(PowerServiceDumpProto.NOTIFY_LONG_DISPATCHED_MS, mNotifyLongDispatched);
- proto.write(PowerServiceDumpProto.NOTIFY_LONG_NEXT_CHECK_MS, mNotifyLongNextCheck);
+ proto.write(PowerManagerServiceDumpProto.NOTIFY_LONG_SCHEDULED_MS, mNotifyLongScheduled);
+ proto.write(PowerManagerServiceDumpProto.NOTIFY_LONG_DISPATCHED_MS, mNotifyLongDispatched);
+ proto.write(PowerManagerServiceDumpProto.NOTIFY_LONG_NEXT_CHECK_MS, mNotifyLongNextCheck);
- final long userActivityToken = proto.start(PowerServiceDumpProto.USER_ACTIVITY);
+ final long userActivityToken = proto.start(PowerManagerServiceDumpProto.USER_ACTIVITY);
proto.write(
- PowerServiceDumpProto.UserActivityProto.IS_SCREEN_BRIGHT,
+ PowerManagerServiceDumpProto.UserActivityProto.IS_SCREEN_BRIGHT,
(mUserActivitySummary & USER_ACTIVITY_SCREEN_BRIGHT) != 0);
proto.write(
- PowerServiceDumpProto.UserActivityProto.IS_SCREEN_DIM,
+ PowerManagerServiceDumpProto.UserActivityProto.IS_SCREEN_DIM,
(mUserActivitySummary & USER_ACTIVITY_SCREEN_DIM) != 0);
proto.write(
- PowerServiceDumpProto.UserActivityProto.IS_SCREEN_DREAM,
+ PowerManagerServiceDumpProto.UserActivityProto.IS_SCREEN_DREAM,
(mUserActivitySummary & USER_ACTIVITY_SCREEN_DREAM) != 0);
proto.end(userActivityToken);
proto.write(
- PowerServiceDumpProto.IS_REQUEST_WAIT_FOR_NEGATIVE_PROXIMITY,
+ PowerManagerServiceDumpProto.IS_REQUEST_WAIT_FOR_NEGATIVE_PROXIMITY,
mRequestWaitForNegativeProximity);
- proto.write(PowerServiceDumpProto.IS_SANDMAN_SCHEDULED, mSandmanScheduled);
- proto.write(PowerServiceDumpProto.IS_SANDMAN_SUMMONED, mSandmanSummoned);
- proto.write(PowerServiceDumpProto.IS_LOW_POWER_MODE_ENABLED, mLowPowerModeEnabled);
- proto.write(PowerServiceDumpProto.IS_BATTERY_LEVEL_LOW, mBatteryLevelLow);
- proto.write(PowerServiceDumpProto.IS_LIGHT_DEVICE_IDLE_MODE, mLightDeviceIdleMode);
- proto.write(PowerServiceDumpProto.IS_DEVICE_IDLE_MODE, mDeviceIdleMode);
+ proto.write(PowerManagerServiceDumpProto.IS_SANDMAN_SCHEDULED, mSandmanScheduled);
+ proto.write(PowerManagerServiceDumpProto.IS_SANDMAN_SUMMONED, mSandmanSummoned);
+ proto.write(PowerManagerServiceDumpProto.IS_LOW_POWER_MODE_ENABLED, mLowPowerModeEnabled);
+ proto.write(PowerManagerServiceDumpProto.IS_BATTERY_LEVEL_LOW, mBatteryLevelLow);
+ proto.write(PowerManagerServiceDumpProto.IS_LIGHT_DEVICE_IDLE_MODE, mLightDeviceIdleMode);
+ proto.write(PowerManagerServiceDumpProto.IS_DEVICE_IDLE_MODE, mDeviceIdleMode);
for (int id : mDeviceIdleWhitelist) {
- proto.write(PowerServiceDumpProto.DEVICE_IDLE_WHITELIST, id);
+ proto.write(PowerManagerServiceDumpProto.DEVICE_IDLE_WHITELIST, id);
}
for (int id : mDeviceIdleTempWhitelist) {
- proto.write(PowerServiceDumpProto.DEVICE_IDLE_TEMP_WHITELIST, id);
+ proto.write(PowerManagerServiceDumpProto.DEVICE_IDLE_TEMP_WHITELIST, id);
}
- proto.write(PowerServiceDumpProto.LAST_WAKE_TIME_MS, mLastWakeTime);
- proto.write(PowerServiceDumpProto.LAST_SLEEP_TIME_MS, mLastSleepTime);
- proto.write(PowerServiceDumpProto.LAST_USER_ACTIVITY_TIME_MS, mLastUserActivityTime);
+ proto.write(PowerManagerServiceDumpProto.LAST_WAKE_TIME_MS, mLastWakeTime);
+ proto.write(PowerManagerServiceDumpProto.LAST_SLEEP_TIME_MS, mLastSleepTime);
+ proto.write(PowerManagerServiceDumpProto.LAST_USER_ACTIVITY_TIME_MS, mLastUserActivityTime);
proto.write(
- PowerServiceDumpProto.LAST_USER_ACTIVITY_TIME_NO_CHANGE_LIGHTS_MS,
+ PowerManagerServiceDumpProto.LAST_USER_ACTIVITY_TIME_NO_CHANGE_LIGHTS_MS,
mLastUserActivityTimeNoChangeLights);
proto.write(
- PowerServiceDumpProto.LAST_INTERACTIVE_POWER_HINT_TIME_MS,
+ PowerManagerServiceDumpProto.LAST_INTERACTIVE_POWER_HINT_TIME_MS,
mLastInteractivePowerHintTime);
proto.write(
- PowerServiceDumpProto.LAST_SCREEN_BRIGHTNESS_BOOST_TIME_MS,
+ PowerManagerServiceDumpProto.LAST_SCREEN_BRIGHTNESS_BOOST_TIME_MS,
mLastScreenBrightnessBoostTime);
proto.write(
- PowerServiceDumpProto.IS_SCREEN_BRIGHTNESS_BOOST_IN_PROGRESS,
+ PowerManagerServiceDumpProto.IS_SCREEN_BRIGHTNESS_BOOST_IN_PROGRESS,
mScreenBrightnessBoostInProgress);
- proto.write(PowerServiceDumpProto.IS_DISPLAY_READY, mDisplayReady);
+ proto.write(PowerManagerServiceDumpProto.IS_DISPLAY_READY, mDisplayReady);
proto.write(
- PowerServiceDumpProto.IS_HOLDING_WAKE_LOCK_SUSPEND_BLOCKER,
+ PowerManagerServiceDumpProto.IS_HOLDING_WAKE_LOCK_SUSPEND_BLOCKER,
mHoldingWakeLockSuspendBlocker);
proto.write(
- PowerServiceDumpProto.IS_HOLDING_DISPLAY_SUSPEND_BLOCKER,
+ PowerManagerServiceDumpProto.IS_HOLDING_DISPLAY_SUSPEND_BLOCKER,
mHoldingDisplaySuspendBlocker);
final long settingsAndConfigurationToken =
- proto.start(PowerServiceDumpProto.SETTINGS_AND_CONFIGURATION);
+ proto.start(PowerManagerServiceDumpProto.SETTINGS_AND_CONFIGURATION);
proto.write(
PowerServiceSettingsAndConfigurationDumpProto
.IS_DECOUPLE_HAL_AUTO_SUSPEND_MODE_FROM_DISPLAY_CONFIG,
@@ -3698,42 +3694,43 @@
final int sleepTimeout = getSleepTimeoutLocked();
final int screenOffTimeout = getScreenOffTimeoutLocked(sleepTimeout);
final int screenDimDuration = getScreenDimDurationLocked(screenOffTimeout);
- proto.write(PowerServiceDumpProto.SLEEP_TIMEOUT_MS, sleepTimeout);
- proto.write(PowerServiceDumpProto.SCREEN_OFF_TIMEOUT_MS, screenOffTimeout);
- proto.write(PowerServiceDumpProto.SCREEN_DIM_DURATION_MS, screenDimDuration);
- proto.write(PowerServiceDumpProto.ARE_UIDS_CHANGING, mUidsChanging);
- proto.write(PowerServiceDumpProto.ARE_UIDS_CHANGED, mUidsChanged);
+ proto.write(PowerManagerServiceDumpProto.SLEEP_TIMEOUT_MS, sleepTimeout);
+ proto.write(PowerManagerServiceDumpProto.SCREEN_OFF_TIMEOUT_MS, screenOffTimeout);
+ proto.write(PowerManagerServiceDumpProto.SCREEN_DIM_DURATION_MS, screenDimDuration);
+ proto.write(PowerManagerServiceDumpProto.ARE_UIDS_CHANGING, mUidsChanging);
+ proto.write(PowerManagerServiceDumpProto.ARE_UIDS_CHANGED, mUidsChanged);
for (int i = 0; i < mUidState.size(); i++) {
final UidState state = mUidState.valueAt(i);
- final long uIDToken = proto.start(PowerServiceDumpProto.UIDS);
+ final long uIDToken = proto.start(PowerManagerServiceDumpProto.UID_STATES);
final int uid = mUidState.keyAt(i);
- proto.write(PowerServiceDumpProto.UidProto.UID, uid);
- proto.write(PowerServiceDumpProto.UidProto.UID_STRING, UserHandle.formatUid(uid));
- proto.write(PowerServiceDumpProto.UidProto.IS_ACTIVE, state.mActive);
- proto.write(PowerServiceDumpProto.UidProto.NUM_WAKE_LOCKS, state.mNumWakeLocks);
+ proto.write(PowerManagerServiceDumpProto.UidStateProto.UID, uid);
+ proto.write(PowerManagerServiceDumpProto.UidStateProto.UID_STRING, UserHandle.formatUid(uid));
+ proto.write(PowerManagerServiceDumpProto.UidStateProto.IS_ACTIVE, state.mActive);
+ proto.write(PowerManagerServiceDumpProto.UidStateProto.NUM_WAKE_LOCKS, state.mNumWakeLocks);
if (state.mProcState == ActivityManager.PROCESS_STATE_UNKNOWN) {
- proto.write(PowerServiceDumpProto.UidProto.IS_PROCESS_STATE_UNKNOWN, true);
+ proto.write(PowerManagerServiceDumpProto.UidStateProto.IS_PROCESS_STATE_UNKNOWN, true);
} else {
- proto.write(PowerServiceDumpProto.UidProto.PROCESS_STATE, state.mProcState);
+ proto.write(PowerManagerServiceDumpProto.UidStateProto.PROCESS_STATE,
+ ActivityManager.processStateAmToProto(state.mProcState));
}
proto.end(uIDToken);
}
- mHandler.getLooper().writeToProto(proto, PowerServiceDumpProto.LOOPER);
+ mHandler.getLooper().writeToProto(proto, PowerManagerServiceDumpProto.LOOPER);
for (WakeLock wl : mWakeLocks) {
- wl.writeToProto(proto, PowerServiceDumpProto.WAKE_LOCKS);
+ wl.writeToProto(proto, PowerManagerServiceDumpProto.WAKE_LOCKS);
}
for (SuspendBlocker sb : mSuspendBlockers) {
- sb.writeToProto(proto, PowerServiceDumpProto.SUSPEND_BLOCKERS);
+ sb.writeToProto(proto, PowerManagerServiceDumpProto.SUSPEND_BLOCKERS);
}
wcd = mWirelessChargerDetector;
}
if (wcd != null) {
- wcd.writeToProto(proto, PowerServiceDumpProto.WIRELESS_CHARGER_DETECTOR);
+ wcd.writeToProto(proto, PowerManagerServiceDumpProto.WIRELESS_CHARGER_DETECTOR);
}
proto.flush();
}
diff --git a/services/core/java/com/android/server/power/WirelessChargerDetector.java b/services/core/java/com/android/server/power/WirelessChargerDetector.java
index 6ee9dcd..54487e3 100644
--- a/services/core/java/com/android/server/power/WirelessChargerDetector.java
+++ b/services/core/java/com/android/server/power/WirelessChargerDetector.java
@@ -24,7 +24,6 @@
import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;
-import android.service.power.WirelessChargerDetectorProto;
import android.util.Slog;
import android.util.TimeUtils;
import android.util.proto.ProtoOutputStream;
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 5d03493..e873d32 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -1621,10 +1621,10 @@
@CallSuper
@Override
- public void writeToProto(ProtoOutputStream proto, long fieldId) {
+ public void writeToProto(ProtoOutputStream proto, long fieldId, boolean trim) {
final long token = proto.start(fieldId);
writeNameToProto(proto, NAME);
- super.writeToProto(proto, WINDOW_TOKEN);
+ super.writeToProto(proto, WINDOW_TOKEN, trim);
proto.end(token);
}
diff --git a/services/core/java/com/android/server/wm/ConfigurationContainer.java b/services/core/java/com/android/server/wm/ConfigurationContainer.java
index a4ab3ba..cc94807 100644
--- a/services/core/java/com/android/server/wm/ConfigurationContainer.java
+++ b/services/core/java/com/android/server/wm/ConfigurationContainer.java
@@ -50,6 +50,9 @@
/** Contains override configuration settings applied to this configuration container. */
private Configuration mOverrideConfiguration = new Configuration();
+ /** True if mOverrideConfiguration is not empty */
+ private boolean mHasOverrideConfiguration;
+
/**
* Contains full configuration applied to this configuration container. Corresponds to full
* parent's config with applied {@link #mOverrideConfiguration}.
@@ -101,6 +104,9 @@
* @see #mFullConfiguration
*/
public void onOverrideConfigurationChanged(Configuration overrideConfiguration) {
+ // Pre-compute this here, so we don't need to go through the entire Configuration when
+ // writing to proto (which has significant cost if we write a lot of empty configurations).
+ mHasOverrideConfiguration = !Configuration.EMPTY.equals(overrideConfiguration);
mOverrideConfiguration.setTo(overrideConfiguration);
// Update full configuration of this container and all its children.
final ConfigurationContainer parent = getParent();
@@ -330,18 +336,23 @@
* Write to a protocol buffer output stream. Protocol buffer message definition is at
* {@link com.android.server.wm.proto.ConfigurationContainerProto}.
*
- * @param protoOutputStream Stream to write the ConfigurationContainer object to.
- * @param fieldId Field Id of the ConfigurationContainer as defined in the parent
- * message.
+ * @param proto Stream to write the ConfigurationContainer object to.
+ * @param fieldId Field Id of the ConfigurationContainer as defined in the parent
+ * message.
+ * @param trim If true, reduce amount of data written.
* @hide
*/
@CallSuper
- public void writeToProto(ProtoOutputStream protoOutputStream, long fieldId) {
- final long token = protoOutputStream.start(fieldId);
- mOverrideConfiguration.writeToProto(protoOutputStream, OVERRIDE_CONFIGURATION);
- mFullConfiguration.writeToProto(protoOutputStream, FULL_CONFIGURATION);
- mMergedOverrideConfiguration.writeToProto(protoOutputStream, MERGED_OVERRIDE_CONFIGURATION);
- protoOutputStream.end(token);
+ public void writeToProto(ProtoOutputStream proto, long fieldId, boolean trim) {
+ final long token = proto.start(fieldId);
+ if (!trim || mHasOverrideConfiguration) {
+ mOverrideConfiguration.writeToProto(proto, OVERRIDE_CONFIGURATION);
+ }
+ if (!trim) {
+ mFullConfiguration.writeToProto(proto, FULL_CONFIGURATION);
+ mMergedOverrideConfiguration.writeToProto(proto, MERGED_OVERRIDE_CONFIGURATION);
+ }
+ proto.end(token);
}
/**
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 03fdc96..4c6ab3f 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -2137,27 +2137,27 @@
@CallSuper
@Override
- public void writeToProto(ProtoOutputStream proto, long fieldId) {
+ public void writeToProto(ProtoOutputStream proto, long fieldId, boolean trim) {
final long token = proto.start(fieldId);
- super.writeToProto(proto, WINDOW_CONTAINER);
+ super.writeToProto(proto, WINDOW_CONTAINER, trim);
proto.write(ID, mDisplayId);
for (int stackNdx = mTaskStackContainers.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
final TaskStack stack = mTaskStackContainers.getChildAt(stackNdx);
- stack.writeToProto(proto, STACKS);
+ stack.writeToProto(proto, STACKS, trim);
}
mDividerControllerLocked.writeToProto(proto, DOCKED_STACK_DIVIDER_CONTROLLER);
mPinnedStackControllerLocked.writeToProto(proto, PINNED_STACK_CONTROLLER);
for (int i = mAboveAppWindowsContainers.getChildCount() - 1; i >= 0; --i) {
final WindowToken windowToken = mAboveAppWindowsContainers.getChildAt(i);
- windowToken.writeToProto(proto, ABOVE_APP_WINDOWS);
+ windowToken.writeToProto(proto, ABOVE_APP_WINDOWS, trim);
}
for (int i = mBelowAppWindowsContainers.getChildCount() - 1; i >= 0; --i) {
final WindowToken windowToken = mBelowAppWindowsContainers.getChildAt(i);
- windowToken.writeToProto(proto, BELOW_APP_WINDOWS);
+ windowToken.writeToProto(proto, BELOW_APP_WINDOWS, trim);
}
for (int i = mImeWindowsContainers.getChildCount() - 1; i >= 0; --i) {
final WindowToken windowToken = mImeWindowsContainers.getChildAt(i);
- windowToken.writeToProto(proto, IME_WINDOWS);
+ windowToken.writeToProto(proto, IME_WINDOWS, trim);
}
proto.write(DPI, mBaseDisplayDensity);
mDisplayInfo.writeToProto(proto, DISPLAY_INFO);
diff --git a/services/core/java/com/android/server/wm/DragDropController.java b/services/core/java/com/android/server/wm/DragDropController.java
new file mode 100644
index 0000000..36871b1
--- /dev/null
+++ b/services/core/java/com/android/server/wm/DragDropController.java
@@ -0,0 +1,306 @@
+/*
+ * Copyright (C) 2017 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.wm;
+
+import static android.graphics.PixelFormat.TRANSLUCENT;
+import static android.view.SurfaceControl.HIDDEN;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DRAG;
+import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS;
+import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS;
+import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
+
+import android.content.ClipData;
+import android.os.Binder;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Message;
+import android.util.Slog;
+import android.view.Display;
+import android.view.IWindow;
+import android.view.Surface;
+import android.view.Surface.OutOfResourcesException;
+import android.view.SurfaceControl;
+import android.view.SurfaceSession;
+import android.view.View;
+import com.android.server.wm.WindowManagerService.H;
+
+/**
+ * Managing drag and drop operations initiated by View#startDragAndDrop.
+ */
+class DragDropController {
+ private static final float DRAG_SHADOW_ALPHA_TRANSPARENT = .7071f;
+ private static final long DRAG_TIMEOUT_MS = 5000;
+
+ IBinder prepareDrag(WindowManagerService service, SurfaceSession session, int callerPid,
+ int callerUid, IWindow window, int flags, int width, int height, Surface outSurface) {
+ if (DEBUG_DRAG) {
+ Slog.d(TAG_WM, "prepare drag surface: w=" + width + " h=" + height
+ + " flags=" + Integer.toHexString(flags) + " win=" + window
+ + " asbinder=" + window.asBinder());
+ }
+
+ IBinder token = null;
+
+ synchronized (service.mWindowMap) {
+ try {
+ if (service.mDragState == null) {
+ // TODO(multi-display): support other displays
+ final DisplayContent displayContent =
+ service.getDefaultDisplayContentLocked();
+ final Display display = displayContent.getDisplay();
+
+ SurfaceControl surface = new SurfaceControl(session, "drag surface",
+ width, height, TRANSLUCENT, HIDDEN);
+ surface.setLayerStack(display.getLayerStack());
+ float alpha = 1;
+ if ((flags & View.DRAG_FLAG_OPAQUE) == 0) {
+ alpha = DRAG_SHADOW_ALPHA_TRANSPARENT;
+ }
+ surface.setAlpha(alpha);
+
+ if (SHOW_TRANSACTIONS) Slog.i(TAG_WM, " DRAG "
+ + surface + ": CREATE");
+ outSurface.copyFrom(surface);
+ final IBinder winBinder = window.asBinder();
+ token = new Binder();
+ service.mDragState =
+ new DragState(service, token, surface, flags, winBinder);
+ service.mDragState.mPid = callerPid;
+ service.mDragState.mUid = callerUid;
+ service.mDragState.mOriginalAlpha = alpha;
+ token = service.mDragState.mToken = new Binder();
+
+ // 5 second timeout for this window to actually begin the drag
+ service.mH.removeMessages(H.DRAG_START_TIMEOUT, winBinder);
+ Message msg = service.mH.obtainMessage(H.DRAG_START_TIMEOUT, winBinder);
+ service.mH.sendMessageDelayed(msg, DRAG_TIMEOUT_MS);
+ } else {
+ Slog.w(TAG_WM, "Drag already in progress");
+ }
+ } catch (OutOfResourcesException e) {
+ Slog.e(TAG_WM, "Can't allocate drag surface w=" + width + " h=" + height,
+ e);
+ if (service.mDragState != null) {
+ service.mDragState.reset();
+ service.mDragState = null;
+ }
+ }
+ }
+
+ return token;
+ }
+
+ boolean performDrag(WindowManagerService service, IWindow window, IBinder dragToken,
+ int touchSource, float touchX, float touchY, float thumbCenterX, float thumbCenterY,
+ ClipData data) {
+ if (DEBUG_DRAG) {
+ Slog.d(TAG_WM, "perform drag: win=" + window + " data=" + data);
+ }
+
+ synchronized (service.mWindowMap) {
+ if (service.mDragState == null) {
+ Slog.w(TAG_WM, "No drag prepared");
+ throw new IllegalStateException("performDrag() without prepareDrag()");
+ }
+
+ if (dragToken != service.mDragState.mToken) {
+ Slog.w(TAG_WM, "Performing mismatched drag");
+ throw new IllegalStateException("performDrag() does not match prepareDrag()");
+ }
+
+ final WindowState callingWin = service.windowForClientLocked(null, window, false);
+ if (callingWin == null) {
+ Slog.w(TAG_WM, "Bad requesting window " + window);
+ return false; // !!! TODO: throw here?
+ }
+
+ // !!! TODO: if input is not still focused on the initiating window, fail
+ // the drag initiation (e.g. an alarm window popped up just as the application
+ // called performDrag()
+
+ service.mH.removeMessages(H.DRAG_START_TIMEOUT, window.asBinder());
+
+ // !!! TODO: extract the current touch (x, y) in screen coordinates. That
+ // will let us eliminate the (touchX,touchY) parameters from the API.
+
+ // !!! FIXME: put all this heavy stuff onto the mH looper, as well as
+ // the actual drag event dispatch stuff in the dragstate
+
+ final DisplayContent displayContent = callingWin.getDisplayContent();
+ if (displayContent == null) {
+ return false;
+ }
+ Display display = displayContent.getDisplay();
+ service.mDragState.register(display);
+ if (!service.mInputManager.transferTouchFocus(callingWin.mInputChannel,
+ service.mDragState.getInputChannel())) {
+ Slog.e(TAG_WM, "Unable to transfer touch focus");
+ service.mDragState.unregister();
+ service.mDragState.reset();
+ service.mDragState = null;
+ return false;
+ }
+
+ service.mDragState.mDisplayContent = displayContent;
+ service.mDragState.mData = data;
+ service.mDragState.broadcastDragStartedLw(touchX, touchY);
+ service.mDragState.overridePointerIconLw(touchSource);
+
+ // remember the thumb offsets for later
+ service.mDragState.mThumbOffsetX = thumbCenterX;
+ service.mDragState.mThumbOffsetY = thumbCenterY;
+
+ // Make the surface visible at the proper location
+ final SurfaceControl surfaceControl = service.mDragState.mSurfaceControl;
+ if (SHOW_LIGHT_TRANSACTIONS) Slog.i(
+ TAG_WM, ">>> OPEN TRANSACTION performDrag");
+ service.openSurfaceTransaction();
+ try {
+ surfaceControl.setPosition(touchX - thumbCenterX,
+ touchY - thumbCenterY);
+ surfaceControl.setLayer(service.mDragState.getDragLayerLw());
+ surfaceControl.setLayerStack(display.getLayerStack());
+ surfaceControl.show();
+ } finally {
+ service.closeSurfaceTransaction();
+ if (SHOW_LIGHT_TRANSACTIONS) Slog.i(
+ TAG_WM, "<<< CLOSE TRANSACTION performDrag");
+ }
+
+ service.mDragState.notifyLocationLw(touchX, touchY);
+ }
+
+ return true; // success!
+ }
+
+ void reportDropResult(WindowManagerService service, IWindow window, boolean consumed) {
+ IBinder token = window.asBinder();
+ if (DEBUG_DRAG) {
+ Slog.d(TAG_WM, "Drop result=" + consumed + " reported by " + token);
+ }
+
+ synchronized (service.mWindowMap) {
+ if (service.mDragState == null) {
+ // Most likely the drop recipient ANRed and we ended the drag
+ // out from under it. Log the issue and move on.
+ Slog.w(TAG_WM, "Drop result given but no drag in progress");
+ return;
+ }
+
+ if (service.mDragState.mToken != token) {
+ // We're in a drag, but the wrong window has responded.
+ Slog.w(TAG_WM, "Invalid drop-result claim by " + window);
+ throw new IllegalStateException("reportDropResult() by non-recipient");
+ }
+
+ // The right window has responded, even if it's no longer around,
+ // so be sure to halt the timeout even if the later WindowState
+ // lookup fails.
+ service.mH.removeMessages(H.DRAG_END_TIMEOUT, window.asBinder());
+ WindowState callingWin = service.windowForClientLocked(null, window, false);
+ if (callingWin == null) {
+ Slog.w(TAG_WM, "Bad result-reporting window " + window);
+ return; // !!! TODO: throw here?
+ }
+
+ service.mDragState.mDragResult = consumed;
+ service.mDragState.endDragLw();
+ }
+ }
+
+ void cancelDragAndDrop(WindowManagerService service, IBinder dragToken) {
+ if (DEBUG_DRAG) {
+ Slog.d(TAG_WM, "cancelDragAndDrop");
+ }
+
+ synchronized (service.mWindowMap) {
+ if (service.mDragState == null) {
+ Slog.w(TAG_WM, "cancelDragAndDrop() without prepareDrag()");
+ throw new IllegalStateException("cancelDragAndDrop() without prepareDrag()");
+ }
+
+ if (service.mDragState.mToken != dragToken) {
+ Slog.w(TAG_WM,
+ "cancelDragAndDrop() does not match prepareDrag()");
+ throw new IllegalStateException(
+ "cancelDragAndDrop() does not match prepareDrag()");
+ }
+
+ service.mDragState.mDragResult = false;
+ service.mDragState.cancelDragLw();
+ }
+ }
+
+ void dragRecipientEntered(IWindow window) {
+ if (DEBUG_DRAG) {
+ Slog.d(TAG_WM, "Drag into new candidate view @ " + window.asBinder());
+ }
+ }
+
+ void dragRecipientExited(IWindow window) {
+ if (DEBUG_DRAG) {
+ Slog.d(TAG_WM, "Drag from old candidate view @ " + window.asBinder());
+ }
+ }
+
+ void handleMessage(WindowManagerService service, Message msg) {
+ switch (msg.what) {
+ case H.DRAG_START_TIMEOUT: {
+ IBinder win = (IBinder) msg.obj;
+ if (DEBUG_DRAG) {
+ Slog.w(TAG_WM, "Timeout starting drag by win " + win);
+ }
+ synchronized (service.mWindowMap) {
+ // !!! TODO: ANR the app that has failed to start the drag in time
+ if (service.mDragState != null) {
+ service.mDragState.unregister();
+ service.mDragState.reset();
+ service.mDragState = null;
+ }
+ }
+ break;
+ }
+
+ case H.DRAG_END_TIMEOUT: {
+ IBinder win = (IBinder) msg.obj;
+ if (DEBUG_DRAG) {
+ Slog.w(TAG_WM, "Timeout ending drag to win " + win);
+ }
+ synchronized (service.mWindowMap) {
+ // !!! TODO: ANR the drag-receiving app
+ if (service.mDragState != null) {
+ service.mDragState.mDragResult = false;
+ service.mDragState.endDragLw();
+ }
+ }
+ break;
+ }
+
+ case H.TEAR_DOWN_DRAG_AND_DROP_INPUT: {
+ if (DEBUG_DRAG)
+ Slog.d(TAG_WM, "Drag ending; tearing down input channel");
+ DragState.InputInterceptor interceptor = (DragState.InputInterceptor) msg.obj;
+ if (interceptor != null) {
+ synchronized (service.mWindowMap) {
+ interceptor.tearDown();
+ }
+ }
+ break;
+ }
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index fd57470..a710441 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -1081,19 +1081,21 @@
@CallSuper
@Override
- public void writeToProto(ProtoOutputStream proto, long fieldId) {
+ public void writeToProto(ProtoOutputStream proto, long fieldId, boolean trim) {
final long token = proto.start(fieldId);
- super.writeToProto(proto, WINDOW_CONTAINER);
+ super.writeToProto(proto, WINDOW_CONTAINER, trim);
if (mService.mDisplayReady) {
final int count = mChildren.size();
for (int i = 0; i < count; ++i) {
final DisplayContent displayContent = mChildren.get(i);
- displayContent.writeToProto(proto, DISPLAYS);
+ displayContent.writeToProto(proto, DISPLAYS, trim);
}
}
- forAllWindows((w) -> {
- w.writeIdentifierToProto(proto, WINDOWS);
- }, true);
+ if (!trim) {
+ forAllWindows((w) -> {
+ w.writeIdentifierToProto(proto, WINDOWS);
+ }, true);
+ }
proto.end(token);
}
diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java
index 2bb0235..717c577 100644
--- a/services/core/java/com/android/server/wm/Session.java
+++ b/services/core/java/com/android/server/wm/Session.java
@@ -81,6 +81,7 @@
private final Set<WindowSurfaceController> mAppOverlaySurfaces = new HashSet<>();
// Set of visible alert window surfaces connected to this session.
private final Set<WindowSurfaceController> mAlertWindowSurfaces = new HashSet<>();
+ private final DragDropController mDragDropController;
final boolean mCanAddInternalSystemWindow;
final boolean mCanHideNonSystemOverlayWindows;
final boolean mCanAcquireSleepToken;
@@ -106,6 +107,7 @@
mCanAcquireSleepToken = service.mContext.checkCallingOrSelfPermission(DEVICE_POWER)
== PERMISSION_GRANTED;
mShowingAlertWindowNotificationAllowed = mService.mShowAlertWindowNotifications;
+ mDragDropController = mService.mDragDropController;
StringBuilder sb = new StringBuilder();
sb.append("Session{");
sb.append(Integer.toHexString(System.identityHashCode(this)));
@@ -304,94 +306,56 @@
/* Drag/drop */
@Override
- public IBinder prepareDrag(IWindow window, int flags,
- int width, int height, Surface outSurface) {
- return mService.prepareDragSurface(window, mSurfaceSession, flags,
- width, height, outSurface);
+ public IBinder prepareDrag(IWindow window, int flags, int width, int height,
+ Surface outSurface) {
+ final int callerPid = Binder.getCallingPid();
+ final int callerUid = Binder.getCallingUid();
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ return mDragDropController.prepareDrag(
+ mService, mSurfaceSession, callerPid, callerUid, window, flags, width, height,
+ outSurface);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
}
@Override
public boolean performDrag(IWindow window, IBinder dragToken,
int touchSource, float touchX, float touchY, float thumbCenterX, float thumbCenterY,
ClipData data) {
- if (DEBUG_DRAG) {
- Slog.d(TAG_WM, "perform drag: win=" + window + " data=" + data);
+ return mDragDropController.performDrag(mService, window, dragToken, touchSource,
+ touchX, touchY, thumbCenterX, thumbCenterY, data);
+ }
+
+ @Override
+ public void reportDropResult(IWindow window, boolean consumed) {
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ mDragDropController.reportDropResult(mService, window, consumed);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
}
+ }
- synchronized (mService.mWindowMap) {
- if (mService.mDragState == null) {
- Slog.w(TAG_WM, "No drag prepared");
- throw new IllegalStateException("performDrag() without prepareDrag()");
- }
-
- if (dragToken != mService.mDragState.mToken) {
- Slog.w(TAG_WM, "Performing mismatched drag");
- throw new IllegalStateException("performDrag() does not match prepareDrag()");
- }
-
- WindowState callingWin = mService.windowForClientLocked(null, window, false);
- if (callingWin == null) {
- Slog.w(TAG_WM, "Bad requesting window " + window);
- return false; // !!! TODO: throw here?
- }
-
- // !!! TODO: if input is not still focused on the initiating window, fail
- // the drag initiation (e.g. an alarm window popped up just as the application
- // called performDrag()
-
- mService.mH.removeMessages(H.DRAG_START_TIMEOUT, window.asBinder());
-
- // !!! TODO: extract the current touch (x, y) in screen coordinates. That
- // will let us eliminate the (touchX,touchY) parameters from the API.
-
- // !!! FIXME: put all this heavy stuff onto the mH looper, as well as
- // the actual drag event dispatch stuff in the dragstate
-
- final DisplayContent displayContent = callingWin.getDisplayContent();
- if (displayContent == null) {
- return false;
- }
- Display display = displayContent.getDisplay();
- mService.mDragState.register(display);
- if (!mService.mInputManager.transferTouchFocus(callingWin.mInputChannel,
- mService.mDragState.getInputChannel())) {
- Slog.e(TAG_WM, "Unable to transfer touch focus");
- mService.mDragState.unregister();
- mService.mDragState.reset();
- mService.mDragState = null;
- return false;
- }
-
- mService.mDragState.mDisplayContent = displayContent;
- mService.mDragState.mData = data;
- mService.mDragState.broadcastDragStartedLw(touchX, touchY);
- mService.mDragState.overridePointerIconLw(touchSource);
-
- // remember the thumb offsets for later
- mService.mDragState.mThumbOffsetX = thumbCenterX;
- mService.mDragState.mThumbOffsetY = thumbCenterY;
-
- // Make the surface visible at the proper location
- final SurfaceControl surfaceControl = mService.mDragState.mSurfaceControl;
- if (SHOW_LIGHT_TRANSACTIONS) Slog.i(
- TAG_WM, ">>> OPEN TRANSACTION performDrag");
- mService.openSurfaceTransaction();
- try {
- surfaceControl.setPosition(touchX - thumbCenterX,
- touchY - thumbCenterY);
- surfaceControl.setLayer(mService.mDragState.getDragLayerLw());
- surfaceControl.setLayerStack(display.getLayerStack());
- surfaceControl.show();
- } finally {
- mService.closeSurfaceTransaction();
- if (SHOW_LIGHT_TRANSACTIONS) Slog.i(
- TAG_WM, "<<< CLOSE TRANSACTION performDrag");
- }
-
- mService.mDragState.notifyLocationLw(touchX, touchY);
+ @Override
+ public void cancelDragAndDrop(IBinder dragToken) {
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ mDragDropController.cancelDragAndDrop(mService, dragToken);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
}
+ }
- return true; // success!
+ @Override
+ public void dragRecipientEntered(IWindow window) {
+ mDragDropController.dragRecipientEntered(window);
+ }
+
+ @Override
+ public void dragRecipientExited(IWindow window) {
+ mDragDropController.dragRecipientExited(window);
}
@Override
@@ -408,90 +372,6 @@
}
@Override
- public void reportDropResult(IWindow window, boolean consumed) {
- IBinder token = window.asBinder();
- if (DEBUG_DRAG) {
- Slog.d(TAG_WM, "Drop result=" + consumed + " reported by " + token);
- }
-
- synchronized (mService.mWindowMap) {
- long ident = Binder.clearCallingIdentity();
- try {
- if (mService.mDragState == null) {
- // Most likely the drop recipient ANRed and we ended the drag
- // out from under it. Log the issue and move on.
- Slog.w(TAG_WM, "Drop result given but no drag in progress");
- return;
- }
-
- if (mService.mDragState.mToken != token) {
- // We're in a drag, but the wrong window has responded.
- Slog.w(TAG_WM, "Invalid drop-result claim by " + window);
- throw new IllegalStateException("reportDropResult() by non-recipient");
- }
-
- // The right window has responded, even if it's no longer around,
- // so be sure to halt the timeout even if the later WindowState
- // lookup fails.
- mService.mH.removeMessages(H.DRAG_END_TIMEOUT, window.asBinder());
- WindowState callingWin = mService.windowForClientLocked(null, window, false);
- if (callingWin == null) {
- Slog.w(TAG_WM, "Bad result-reporting window " + window);
- return; // !!! TODO: throw here?
- }
-
- mService.mDragState.mDragResult = consumed;
- mService.mDragState.endDragLw();
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
- }
- }
-
- @Override
- public void cancelDragAndDrop(IBinder dragToken) {
- if (DEBUG_DRAG) {
- Slog.d(TAG_WM, "cancelDragAndDrop");
- }
-
- synchronized (mService.mWindowMap) {
- long ident = Binder.clearCallingIdentity();
- try {
- if (mService.mDragState == null) {
- Slog.w(TAG_WM, "cancelDragAndDrop() without prepareDrag()");
- throw new IllegalStateException("cancelDragAndDrop() without prepareDrag()");
- }
-
- if (mService.mDragState.mToken != dragToken) {
- Slog.w(TAG_WM,
- "cancelDragAndDrop() does not match prepareDrag()");
- throw new IllegalStateException(
- "cancelDragAndDrop() does not match prepareDrag()");
- }
-
- mService.mDragState.mDragResult = false;
- mService.mDragState.cancelDragLw();
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
- }
- }
-
- @Override
- public void dragRecipientEntered(IWindow window) {
- if (DEBUG_DRAG) {
- Slog.d(TAG_WM, "Drag into new candidate view @ " + window.asBinder());
- }
- }
-
- @Override
- public void dragRecipientExited(IWindow window) {
- if (DEBUG_DRAG) {
- Slog.d(TAG_WM, "Drag from old candidate view @ " + window.asBinder());
- }
- }
-
- @Override
public void setWallpaperPosition(IBinder window, float x, float y, float xStep, float yStep) {
synchronized(mService.mWindowMap) {
long ident = Binder.clearCallingIdentity();
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 891d637a..7620cb0 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -725,13 +725,13 @@
@CallSuper
@Override
- public void writeToProto(ProtoOutputStream proto, long fieldId) {
+ public void writeToProto(ProtoOutputStream proto, long fieldId, boolean trim) {
final long token = proto.start(fieldId);
- super.writeToProto(proto, WINDOW_CONTAINER);
+ super.writeToProto(proto, WINDOW_CONTAINER, trim);
proto.write(ID, mTaskId);
for (int i = mChildren.size() - 1; i >= 0; i--) {
final AppWindowToken appWindowToken = mChildren.get(i);
- appWindowToken.writeToProto(proto, APP_WINDOW_TOKENS);
+ appWindowToken.writeToProto(proto, APP_WINDOW_TOKENS, trim);
}
proto.write(FILLS_PARENT, mFillsParent);
mBounds.writeToProto(proto, BOUNDS);
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index 3320274..791accf 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -1232,12 +1232,12 @@
@CallSuper
@Override
- public void writeToProto(ProtoOutputStream proto, long fieldId) {
+ public void writeToProto(ProtoOutputStream proto, long fieldId, boolean trim) {
final long token = proto.start(fieldId);
- super.writeToProto(proto, WINDOW_CONTAINER);
+ super.writeToProto(proto, WINDOW_CONTAINER, trim);
proto.write(ID, mStackId);
for (int taskNdx = mChildren.size() - 1; taskNdx >= 0; taskNdx--) {
- mChildren.get(taskNdx).writeToProto(proto, TASKS);
+ mChildren.get(taskNdx).writeToProto(proto, TASKS, trim);
}
proto.write(FILLS_PARENT, mFillsParent);
mBounds.writeToProto(proto, BOUNDS);
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index 563eb9c..8f4b897 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -677,17 +677,18 @@
* Write to a protocol buffer output stream. Protocol buffer message definition is at
* {@link com.android.server.wm.proto.WindowContainerProto}.
*
- * @param protoOutputStream Stream to write the WindowContainer object to.
- * @param fieldId Field Id of the WindowContainer as defined in the parent message.
+ * @param proto Stream to write the WindowContainer object to.
+ * @param fieldId Field Id of the WindowContainer as defined in the parent message.
+ * @param trim If true, reduce the amount of data written.
* @hide
*/
@CallSuper
@Override
- public void writeToProto(ProtoOutputStream protoOutputStream, long fieldId) {
- final long token = protoOutputStream.start(fieldId);
- super.writeToProto(protoOutputStream, CONFIGURATION_CONTAINER);
- protoOutputStream.write(ORIENTATION, mOrientation);
- protoOutputStream.end(token);
+ public void writeToProto(ProtoOutputStream proto, long fieldId, boolean trim) {
+ final long token = proto.start(fieldId);
+ super.writeToProto(proto, CONFIGURATION_CONTAINER, trim);
+ proto.write(ORIENTATION, mOrientation);
+ proto.end(token);
}
private ForAllWindowsConsumerWrapper obtainConsumerWrapper(Consumer<WindowState> consumer) {
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 5992a5f..ad6fc39 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -357,8 +357,6 @@
// trying to apply a new one.
private static final boolean ALWAYS_KEEP_CURRENT = true;
- private static final float DRAG_SHADOW_ALPHA_TRANSPARENT = .7071f;
-
// Enums for animation scale update types.
@Retention(RetentionPolicy.SOURCE)
@IntDef({WINDOW_ANIMATION_SCALE, TRANSITION_ANIMATION_SCALE, ANIMATION_DURATION_SCALE})
@@ -752,6 +750,7 @@
boolean mAllowTheaterModeWakeFromLayout;
TaskPositioner mTaskPositioner;
+ final DragDropController mDragDropController = new DragDropController();
DragState mDragState = null;
// For frozen screen animations.
@@ -4637,73 +4636,6 @@
}
// -------------------------------------------------------------
- // Drag and drop
- // -------------------------------------------------------------
-
- IBinder prepareDragSurface(IWindow window, SurfaceSession session,
- int flags, int width, int height, Surface outSurface) {
- if (DEBUG_DRAG) {
- Slog.d(TAG_WM, "prepare drag surface: w=" + width + " h=" + height
- + " flags=" + Integer.toHexString(flags) + " win=" + window
- + " asbinder=" + window.asBinder());
- }
-
- final int callerPid = Binder.getCallingPid();
- final int callerUid = Binder.getCallingUid();
- final long origId = Binder.clearCallingIdentity();
- IBinder token = null;
-
- try {
- synchronized (mWindowMap) {
- try {
- if (mDragState == null) {
- // TODO(multi-display): support other displays
- final DisplayContent displayContent = getDefaultDisplayContentLocked();
- final Display display = displayContent.getDisplay();
-
- SurfaceControl surface = new SurfaceControl(session, "drag surface",
- width, height, PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN);
- surface.setLayerStack(display.getLayerStack());
- float alpha = 1;
- if ((flags & View.DRAG_FLAG_OPAQUE) == 0) {
- alpha = DRAG_SHADOW_ALPHA_TRANSPARENT;
- }
- surface.setAlpha(alpha);
-
- if (SHOW_TRANSACTIONS) Slog.i(TAG_WM, " DRAG "
- + surface + ": CREATE");
- outSurface.copyFrom(surface);
- final IBinder winBinder = window.asBinder();
- token = new Binder();
- mDragState = new DragState(this, token, surface, flags, winBinder);
- mDragState.mPid = callerPid;
- mDragState.mUid = callerUid;
- mDragState.mOriginalAlpha = alpha;
- token = mDragState.mToken = new Binder();
-
- // 5 second timeout for this window to actually begin the drag
- mH.removeMessages(H.DRAG_START_TIMEOUT, winBinder);
- Message msg = mH.obtainMessage(H.DRAG_START_TIMEOUT, winBinder);
- mH.sendMessageDelayed(msg, 5000);
- } else {
- Slog.w(TAG_WM, "Drag already in progress");
- }
- } catch (OutOfResourcesException e) {
- Slog.e(TAG_WM, "Can't allocate drag surface w=" + width + " h=" + height, e);
- if (mDragState != null) {
- mDragState.reset();
- mDragState = null;
- }
- }
- }
- } finally {
- Binder.restoreCallingIdentity(origId);
- }
-
- return token;
- }
-
- // -------------------------------------------------------------
// Input Events and Focus Management
// -------------------------------------------------------------
@@ -4866,6 +4798,7 @@
public static final int REPORT_WINDOWS_CHANGE = 19;
public static final int DRAG_START_TIMEOUT = 20;
public static final int DRAG_END_TIMEOUT = 21;
+
public static final int REPORT_HARD_KEYBOARD_STATUS_CHANGE = 22;
public static final int BOOT_TIMEOUT = 23;
public static final int WAITING_FOR_DRAWN_TIMEOUT = 24;
@@ -5120,47 +5053,12 @@
break;
}
- case DRAG_START_TIMEOUT: {
- IBinder win = (IBinder)msg.obj;
- if (DEBUG_DRAG) {
- Slog.w(TAG_WM, "Timeout starting drag by win " + win);
- }
- synchronized (mWindowMap) {
- // !!! TODO: ANR the app that has failed to start the drag in time
- if (mDragState != null) {
- mDragState.unregister();
- mDragState.reset();
- mDragState = null;
- }
- }
- break;
- }
-
- case DRAG_END_TIMEOUT: {
- IBinder win = (IBinder)msg.obj;
- if (DEBUG_DRAG) {
- Slog.w(TAG_WM, "Timeout ending drag to win " + win);
- }
- synchronized (mWindowMap) {
- // !!! TODO: ANR the drag-receiving app
- if (mDragState != null) {
- mDragState.mDragResult = false;
- mDragState.endDragLw();
- }
- }
- break;
- }
-
+ case DRAG_START_TIMEOUT:
+ case DRAG_END_TIMEOUT:
case TEAR_DOWN_DRAG_AND_DROP_INPUT: {
- if (DEBUG_DRAG) Slog.d(TAG_WM, "Drag ending; tearing down input channel");
- DragState.InputInterceptor interceptor = (DragState.InputInterceptor) msg.obj;
- if (interceptor != null) {
- synchronized (mWindowMap) {
- interceptor.tearDown();
- }
- }
+ mDragDropController.handleMessage(WindowManagerService.this, msg);
+ break;
}
- break;
case REPORT_HARD_KEYBOARD_STATUS_CHANGE: {
notifyHardKeyboardStatusChange();
@@ -6532,9 +6430,16 @@
}
}
- private void writeToProtoLocked(ProtoOutputStream proto) {
+ /**
+ * Write to a protocol buffer output stream. Protocol buffer message definition is at
+ * {@link com.android.server.wm.proto.WindowManagerServiceProto}.
+ *
+ * @param proto Stream to write the WindowContainer object to.
+ * @param trim If true, reduce the amount of data written.
+ */
+ private void writeToProtoLocked(ProtoOutputStream proto, boolean trim) {
mPolicy.writeToProto(proto, POLICY);
- mRoot.writeToProto(proto, ROOT_WINDOW_CONTAINER);
+ mRoot.writeToProto(proto, ROOT_WINDOW_CONTAINER, trim);
if (mCurrentFocus != null) {
mCurrentFocus.writeIdentifierToProto(proto, FOCUSED_WINDOW);
}
@@ -6870,7 +6775,7 @@
if (useProto) {
final ProtoOutputStream proto = new ProtoOutputStream(fd);
synchronized (mWindowMap) {
- writeToProtoLocked(proto);
+ writeToProtoLocked(proto, false /* trim */);
}
proto.flush();
return;
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index e171528..4370a76 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -3120,9 +3120,9 @@
@CallSuper
@Override
- public void writeToProto(ProtoOutputStream proto, long fieldId) {
+ public void writeToProto(ProtoOutputStream proto, long fieldId, boolean trim) {
final long token = proto.start(fieldId);
- super.writeToProto(proto, WINDOW_CONTAINER);
+ super.writeToProto(proto, WINDOW_CONTAINER, trim);
writeIdentifierToProto(proto, IDENTIFIER);
proto.write(DISPLAY_ID, getDisplayId());
proto.write(STACK_ID, getStackId());
@@ -3137,7 +3137,7 @@
mWinAnimator.writeToProto(proto, ANIMATOR);
proto.write(ANIMATING_EXIT, mAnimatingExit);
for (int i = 0; i < mChildren.size(); i++) {
- mChildren.get(i).writeToProto(proto, CHILD_WINDOWS);
+ mChildren.get(i).writeToProto(proto, CHILD_WINDOWS, trim);
}
proto.end(token);
}
diff --git a/services/core/java/com/android/server/wm/WindowToken.java b/services/core/java/com/android/server/wm/WindowToken.java
index 943448e..62a2abb 100644
--- a/services/core/java/com/android/server/wm/WindowToken.java
+++ b/services/core/java/com/android/server/wm/WindowToken.java
@@ -267,13 +267,13 @@
@CallSuper
@Override
- public void writeToProto(ProtoOutputStream proto, long fieldId) {
+ public void writeToProto(ProtoOutputStream proto, long fieldId, boolean trim) {
final long token = proto.start(fieldId);
- super.writeToProto(proto, WINDOW_CONTAINER);
+ super.writeToProto(proto, WINDOW_CONTAINER, trim);
proto.write(HASH_CODE, System.identityHashCode(this));
for (int i = 0; i < mChildren.size(); i++) {
final WindowState w = mChildren.get(i);
- w.writeToProto(proto, WINDOWS);
+ w.writeToProto(proto, WINDOWS, trim);
}
proto.end(token);
}
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java
index 9e4a9e9..cb13e85 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java
@@ -51,11 +51,6 @@
@Presubmit
@RunWith(AndroidJUnit4.class)
public class ActivityRecordTests extends ActivityTestsBase {
- private final ComponentName testActivityComponent =
- ComponentName.unflattenFromString("com.foo/.BarActivity");
- private final ComponentName secondaryActivityComponent =
- ComponentName.unflattenFromString("com.foo/.BarActivity2");
-
private ActivityManagerService mService;
private TestActivityStack mStack;
private TaskRecord mTask;
@@ -69,8 +64,8 @@
mService = createActivityManagerService();
mStack = mService.mStackSupervisor.getDefaultDisplay().createStack(
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
- mTask = createTask(mService.mStackSupervisor, testActivityComponent, mStack);
- mActivity = createActivity(mService, testActivityComponent, mTask);
+ mTask = new TaskBuilder(mService.mStackSupervisor).setStack(mStack).build();
+ mActivity = new ActivityBuilder(mService).setTask(mTask).build();
}
@Test
@@ -94,8 +89,8 @@
@Test
public void testNoCleanupMovingActivityInSameStack() throws Exception {
- final TaskRecord newTask =
- createTask(mService.mStackSupervisor, testActivityComponent, mStack);
+ final TaskRecord newTask = new TaskBuilder(mService.mStackSupervisor).setStack(mStack)
+ .build();
mActivity.reparent(newTask, 0, null /*reason*/);
assertEquals(mStack.onActivityRemovedFromStackInvocationCount(), 0);
}
@@ -149,13 +144,13 @@
mService.mSupportsMultiWindow = true;
final TaskRecord task = taskPresent
- ? createTask(mService.mStackSupervisor, testActivityComponent, mStack) : null;
+ ? new TaskBuilder(mService.mStackSupervisor).setStack(mStack).build() : null;
if (task != null) {
task.setResizeMode(taskResizeable ? RESIZE_MODE_RESIZEABLE : RESIZE_MODE_UNRESIZEABLE);
}
- final ActivityRecord record = createActivity(mService, secondaryActivityComponent, task);
+ final ActivityRecord record = new ActivityBuilder(mService).setTask(task).build();
record.info.resizeMode = activityResizeable
? RESIZE_MODE_RESIZEABLE : RESIZE_MODE_UNRESIZEABLE;
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java
index 7f03034..fc17da8 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java
@@ -51,9 +51,6 @@
@Presubmit
@RunWith(AndroidJUnit4.class)
public class ActivityStackSupervisorTests extends ActivityTestsBase {
- private final ComponentName testActivityComponent =
- ComponentName.unflattenFromString("com.foo/.BarActivity");
-
private ActivityManagerService mService;
private ActivityStackSupervisor mSupervisor;
private ActivityStack mFullscreenStack;
@@ -87,15 +84,14 @@
*/
@Test
public void testReplacingTaskInPinnedStack() throws Exception {
- final TaskRecord firstTask = createTask(
- mSupervisor, testActivityComponent, mFullscreenStack);
- final ActivityRecord firstActivity = createActivity(mService, testActivityComponent,
- firstTask);
- // Create a new task on the full screen stack
- final TaskRecord secondTask = createTask(
- mSupervisor, testActivityComponent, mFullscreenStack);
- final ActivityRecord secondActivity = createActivity(mService, testActivityComponent,
- secondTask);
+ final ActivityRecord firstActivity = new ActivityBuilder(mService).setCreateTask(true)
+ .setStack(mFullscreenStack).build();
+ final TaskRecord firstTask = firstActivity.getTask();
+
+ final ActivityRecord secondActivity = new ActivityBuilder(mService).setCreateTask(true)
+ .setStack(mFullscreenStack).build();
+ final TaskRecord secondTask = secondActivity.getTask();
+
mSupervisor.setFocusStackUnchecked("testReplacingTaskInPinnedStack", mFullscreenStack);
// Ensure full screen stack has both tasks.
@@ -142,10 +138,8 @@
*/
@Test
public void testStoppingActivityRemovedWhenResumed() throws Exception {
- final TaskRecord firstTask = createTask(
- mSupervisor, testActivityComponent, mFullscreenStack);
- final ActivityRecord firstActivity = createActivity(mService, testActivityComponent,
- firstTask);
+ final ActivityRecord firstActivity = new ActivityBuilder(mService).setCreateTask(true)
+ .setStack(mFullscreenStack).build();
mSupervisor.mStoppingActivities.add(firstActivity);
firstActivity.completeResumeLocked();
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java
index e17e51b..480b210 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java
@@ -23,7 +23,9 @@
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
+
import static com.android.server.am.ActivityStack.REMOVE_TASK_MODE_DESTROYING;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
@@ -51,11 +53,6 @@
@Presubmit
@RunWith(AndroidJUnit4.class)
public class ActivityStackTests extends ActivityTestsBase {
- private static final ComponentName testActivityComponent =
- ComponentName.unflattenFromString("com.foo/.BarActivity");
- private static final ComponentName testOverlayComponent =
- ComponentName.unflattenFromString("com.foo/.OverlayActivity");
-
private ActivityManagerService mService;
private ActivityStackSupervisor mSupervisor;
private ActivityStack mStack;
@@ -70,7 +67,7 @@
mSupervisor = mService.mStackSupervisor;
mStack = mService.mStackSupervisor.getDefaultDisplay().createStack(
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
- mTask = createTask(mSupervisor, testActivityComponent, mStack);
+ mTask = new TaskBuilder(mSupervisor).setStack(mStack).build();
}
@Test
@@ -82,7 +79,7 @@
@Test
public void testOccupiedTaskCleanupOnRemove() throws Exception {
- final ActivityRecord r = createActivity(mService, testActivityComponent, mTask);
+ final ActivityRecord r = new ActivityBuilder(mService).setTask(mTask).build();
assertNotNull(mTask.getWindowContainerController());
mStack.removeTask(mTask, "testOccupiedTaskCleanupOnRemove", REMOVE_TASK_MODE_DESTROYING);
assertNotNull(mTask.getWindowContainerController());
@@ -90,7 +87,7 @@
@Test
public void testNoPauseDuringResumeTopActivity() throws Exception {
- final ActivityRecord r = createActivity(mService, testActivityComponent, mTask);
+ final ActivityRecord r = new ActivityBuilder(mService).setTask(mTask).build();
// Simulate the a resumed activity set during
// {@link ActivityStack#resumeTopActivityUncheckedLocked}.
@@ -108,7 +105,7 @@
@Test
public void testStopActivityWhenActivityDestroyed() throws Exception {
- final ActivityRecord r = createActivity(mService, testActivityComponent, mTask);
+ final ActivityRecord r = new ActivityBuilder(mService).setTask(mTask).build();
r.info.flags |= ActivityInfo.FLAG_NO_HISTORY;
mSupervisor.setFocusStackUnchecked("testStopActivityWithDestroy", mStack);
mStack.stopActivityLocked(r);
@@ -118,18 +115,23 @@
@Test
public void testFindTaskWithOverlay() throws Exception {
- final ActivityRecord r = createActivity(mService, testActivityComponent, mTask, 0);
+ final ActivityRecord r = new ActivityBuilder(mService)
+ .setCreateTask(true)
+ .setStack(mStack)
+ .setUid(0)
+ .build();
+ final TaskRecord task = r.getTask();
// Overlay must be for a different user to prevent recognizing a matching top activity
- final ActivityRecord taskOverlay = createActivity(mService, testOverlayComponent, mTask,
- UserHandle.PER_USER_RANGE * 2);
+ final ActivityRecord taskOverlay = new ActivityBuilder(mService).setTask(task)
+ .setUid(UserHandle.PER_USER_RANGE * 2).build();
taskOverlay.mTaskOverlay = true;
final ActivityStackSupervisor.FindTaskResult result =
new ActivityStackSupervisor.FindTaskResult();
mStack.findTaskLocked(r, result);
- assertEquals(mTask.getTopActivity(false /* includeOverlays */), r);
- assertEquals(mTask.getTopActivity(true /* includeOverlays */), taskOverlay);
+ assertEquals(task.getTopActivity(false /* includeOverlays */), r);
+ assertEquals(task.getTopActivity(true /* includeOverlays */), taskOverlay);
assertNotNull(result.r);
}
@@ -245,9 +247,8 @@
private <T extends ActivityStack> T createStackForShouldBeVisibleTest(
ActivityDisplay display, int windowingMode, int activityType, boolean onTop) {
final T stack = display.createStack(windowingMode, activityType, onTop);
- // Create a task and activity in the stack so that it has a top running activity.
- final TaskRecord task = createTask(mSupervisor, testActivityComponent, stack);
- final ActivityRecord r = createActivity(mService, testActivityComponent, task, 0);
+ final ActivityRecord r = new ActivityBuilder(mService).setUid(0).setStack(stack)
+ .setCreateTask(true).build();
return stack;
}
}
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityStarterTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityStarterTests.java
index 026abce..5b1e4b7 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityStarterTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityStarterTests.java
@@ -50,9 +50,6 @@
@Presubmit
@RunWith(AndroidJUnit4.class)
public class ActivityStarterTests extends ActivityTestsBase {
- private static final ComponentName testActivityComponent =
- ComponentName.unflattenFromString("com.foo/.BarActivity");
-
private ActivityManagerService mService;
private ActivityStarter mStarter;
@@ -66,9 +63,10 @@
@Test
public void testUpdateLaunchBounds() throws Exception {
// When in a non-resizeable stack, the task bounds should be updated.
- final TaskRecord task = createTask(mService.mStackSupervisor, testActivityComponent,
- mService.mStackSupervisor.getDefaultDisplay().createStack(
- WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */));
+ final TaskRecord task = new TaskBuilder(mService.mStackSupervisor)
+ .setStack(mService.mStackSupervisor.getDefaultDisplay().createStack(
+ WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */))
+ .build();
final Rect bounds = new Rect(10, 10, 100, 100);
mStarter.updateBounds(task, bounds);
@@ -76,9 +74,10 @@
assertEquals(task.getStack().mBounds, null);
// When in a resizeable stack, the stack bounds should be updated as well.
- final TaskRecord task2 = createTask(mService.mStackSupervisor, testActivityComponent,
- mService.mStackSupervisor.getDefaultDisplay().createStack(
- WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD, true /* onTop */));
+ final TaskRecord task2 = new TaskBuilder(mService.mStackSupervisor)
+ .setStack(mService.mStackSupervisor.getDefaultDisplay().createStack(
+ WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD, true /* onTop */))
+ .build();
assertTrue(task2.getStack() instanceof PinnedActivityStack);
mStarter.updateBounds(task2, bounds);
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java b/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java
index 07b49c5..198cc6d 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java
@@ -16,6 +16,8 @@
package com.android.server.am;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.view.Display.DEFAULT_DISPLAY;
import static org.mockito.Mockito.mock;
@@ -76,62 +78,165 @@
}
protected ActivityManagerService createActivityManagerService() {
- final ActivityManagerService service = spy(new TestActivityManagerService(mContext));
+ return setupActivityManagerService(new TestActivityManagerService(mContext));
+ }
+
+ protected ActivityManagerService setupActivityManagerService(ActivityManagerService service) {
+ service = spy(service);
service.mWindowManager = prepareMockWindowManager();
return service;
}
- protected static ActivityRecord createActivity(ActivityManagerService service,
- ComponentName component, TaskRecord task) {
- return createActivity(service, component, task, 0 /* userId */);
- }
+ /**
+ * Builder for creating new activities.
+ */
+ protected static class ActivityBuilder {
+ // An id appended to the end of the component name to make it unique
+ private static int sCurrentActivityId = 0;
- protected static ActivityRecord createActivity(ActivityManagerService service,
- ComponentName component, TaskRecord task, int uid) {
- Intent intent = new Intent();
- intent.setComponent(component);
- final ActivityInfo aInfo = new ActivityInfo();
- aInfo.applicationInfo = new ApplicationInfo();
- aInfo.applicationInfo.packageName = component.getPackageName();
- aInfo.applicationInfo.uid = uid;
- AttributeCache.init(service.mContext);
- final ActivityRecord activity = new ActivityRecord(service, null /* caller */,
- 0 /* launchedFromPid */, 0, null, intent, null,
- aInfo /*aInfo*/, new Configuration(), null /* resultTo */, null /* resultWho */,
- 0 /* reqCode */, false /*componentSpecified*/, false /* rootVoiceInteraction */,
- service.mStackSupervisor, null /* options */, null /* sourceRecord */);
- activity.mWindowContainerController = mock(AppWindowContainerController.class);
+ // Default package name
+ private static final String DEFAULT_PACKAGE = "com.foo";
- if (task != null) {
- task.addActivityToTop(activity);
+ // Default base activity name
+ private static final String DEFAULT_BASE_ACTIVITY_NAME = ".BarActivity";
+
+ private final ActivityManagerService mService;
+
+ private ComponentName mComponent;
+ private TaskRecord mTaskRecord;
+ private int mUid;
+ private boolean mCreateTask;
+ private ActivityStack mStack;
+
+ ActivityBuilder(ActivityManagerService service) {
+ mService = service;
}
- return activity;
+ ActivityBuilder setComponent(ComponentName component) {
+ mComponent = component;
+ return this;
+ }
+
+ ActivityBuilder setTask(TaskRecord task) {
+ mTaskRecord = task;
+ return this;
+ }
+
+ ActivityBuilder setStack(ActivityStack stack) {
+ mStack = stack;
+ return this;
+ }
+
+ ActivityBuilder setCreateTask(boolean createTask) {
+ mCreateTask = createTask;
+ return this;
+ }
+
+ ActivityBuilder setUid(int uid) {
+ mUid = uid;
+ return this;
+ }
+
+ ActivityRecord build() {
+ if (mComponent == null) {
+ final int id = sCurrentActivityId++;
+ mComponent = ComponentName.createRelative(DEFAULT_PACKAGE,
+ DEFAULT_BASE_ACTIVITY_NAME + id);
+ }
+
+ if (mCreateTask) {
+ mTaskRecord = new TaskBuilder(mService.mStackSupervisor)
+ .setComponent(mComponent)
+ .setStack(mStack).build();
+ }
+
+ Intent intent = new Intent();
+ intent.setComponent(mComponent);
+ final ActivityInfo aInfo = new ActivityInfo();
+ aInfo.applicationInfo = new ApplicationInfo();
+ aInfo.applicationInfo.packageName = mComponent.getPackageName();
+ aInfo.applicationInfo.uid = mUid;
+ AttributeCache.init(mService.mContext);
+ final ActivityRecord activity = new ActivityRecord(mService, null /* caller */,
+ 0 /* launchedFromPid */, 0, null, intent, null,
+ aInfo /*aInfo*/, new Configuration(), null /* resultTo */, null /* resultWho */,
+ 0 /* reqCode */, false /*componentSpecified*/, false /* rootVoiceInteraction */,
+ mService.mStackSupervisor, null /* options */, null /* sourceRecord */);
+ activity.mWindowContainerController = mock(AppWindowContainerController.class);
+
+ if (mTaskRecord != null) {
+ mTaskRecord.addActivityToTop(activity);
+ }
+
+ return activity;
+ }
}
- protected static TaskRecord createTask(ActivityStackSupervisor supervisor,
- ComponentName component, ActivityStack stack) {
- return createTask(supervisor, component, 0 /* flags */, 0 /* taskId */, stack);
- }
+ /**
+ * Builder for creating new tasks.
+ */
+ protected static class TaskBuilder {
+ private final ActivityStackSupervisor mSupervisor;
- protected static TaskRecord createTask(ActivityStackSupervisor supervisor,
- ComponentName component, int flags, int taskId, ActivityStack stack) {
- final ActivityInfo aInfo = new ActivityInfo();
- aInfo.applicationInfo = new ApplicationInfo();
- aInfo.applicationInfo.packageName = component.getPackageName();
+ private ComponentName mComponent;
+ private String mPackage;
+ private int mFlags = 0;
+ private int mTaskId = 0;
- Intent intent = new Intent();
- intent.setComponent(component);
- intent.setFlags(flags);
+ private ActivityStack mStack;
- final TaskRecord task = new TaskRecord(supervisor.mService, taskId, aInfo,
- intent /*intent*/, null /*_taskDescription*/);
- supervisor.setFocusStackUnchecked("test", stack);
- stack.addTask(task, true, "creating test task");
- task.setStack(stack);
- task.setWindowContainerController(mock(TaskWindowContainerController.class));
+ TaskBuilder(ActivityStackSupervisor supervisor) {
+ mSupervisor = supervisor;
+ }
- return task;
+ TaskBuilder setComponent(ComponentName component) {
+ mComponent = component;
+ return this;
+ }
+
+ TaskBuilder setPackage(String packageName) {
+ mPackage = packageName;
+ return this;
+ }
+
+ TaskBuilder setFlags(int flags) {
+ mFlags = flags;
+ return this;
+ }
+
+ TaskBuilder setTaskId(int taskId) {
+ mTaskId = taskId;
+ return this;
+ }
+
+ TaskBuilder setStack(ActivityStack stack) {
+ mStack = stack;
+ return this;
+ }
+
+ TaskRecord build() {
+ if (mStack == null) {
+ mStack = mSupervisor.getDefaultDisplay().createStack(
+ WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
+ }
+
+ final ActivityInfo aInfo = new ActivityInfo();
+ aInfo.applicationInfo = new ApplicationInfo();
+ aInfo.applicationInfo.packageName = mPackage;
+
+ Intent intent = new Intent();
+ intent.setComponent(mComponent);
+ intent.setFlags(mFlags);
+
+ final TaskRecord task = new TaskRecord(mSupervisor.mService, mTaskId, aInfo,
+ intent /*intent*/, null /*_taskDescription*/);
+ mSupervisor.setFocusStackUnchecked("test", mStack);
+ mStack.addTask(task, true, "creating test task");
+ task.setStack(mStack);
+ task.setWindowContainerController(mock(TaskWindowContainerController.class));
+
+ return task;
+ }
}
/**
diff --git a/services/tests/servicestests/src/com/android/server/am/LaunchingActivityPositionerTests.java b/services/tests/servicestests/src/com/android/server/am/LaunchingActivityPositionerTests.java
index 0007e8a..de831a0 100644
--- a/services/tests/servicestests/src/com/android/server/am/LaunchingActivityPositionerTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/LaunchingActivityPositionerTests.java
@@ -49,9 +49,6 @@
@Presubmit
@RunWith(AndroidJUnit4.class)
public class LaunchingActivityPositionerTests extends ActivityTestsBase {
- private final ComponentName testActivityComponent =
- ComponentName.unflattenFromString("com.foo/.BarActivity");
-
private LaunchingActivityPositioner mPositioner;
private ActivityManagerService mService;
private ActivityStack mStack;
@@ -73,8 +70,8 @@
mStack = mService.mStackSupervisor.getDefaultDisplay().createStack(
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
- mTask = createTask(mService.mStackSupervisor, testActivityComponent, mStack);
- mActivity = createActivity(mService, testActivityComponent, mTask);
+ mTask = new TaskBuilder(mService.mStackSupervisor).setStack(mStack).build();
+ mActivity = new ActivityBuilder(mService).setTask(mTask).build();
}
diff --git a/services/tests/servicestests/src/com/android/server/am/LaunchingTaskPositionerTests.java b/services/tests/servicestests/src/com/android/server/am/LaunchingTaskPositionerTests.java
index 0d64981c..30666c0 100644
--- a/services/tests/servicestests/src/com/android/server/am/LaunchingTaskPositionerTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/LaunchingTaskPositionerTests.java
@@ -52,9 +52,6 @@
@Presubmit
@RunWith(AndroidJUnit4.class)
public class LaunchingTaskPositionerTests extends ActivityTestsBase {
- private final ComponentName testActivityComponent =
- ComponentName.unflattenFromString("com.foo/.BarActivity");
-
private final static int STACK_WIDTH = 100;
private final static int STACK_HEIGHT = 200;
@@ -81,7 +78,7 @@
// We must create the task after resizing to make sure it does not inherit the stack
// dimensions on resize.
- mTask = createTask(mService.mStackSupervisor, testActivityComponent, mStack);
+ mTask = new TaskBuilder(mService.mStackSupervisor).setStack(mStack).build();
mPositioner = new LaunchingTaskPositioner();
@@ -193,11 +190,10 @@
// wrap with try/finally to ensure cleanup of activity/stack.
try {
// empty tasks are ignored in conflicts
- activity = createActivity(mService, testActivityComponent, mTask);
+ activity = new ActivityBuilder(mService).setTask(mTask).build();
// Create secondary task
- secondTask = createTask(mService.mStackSupervisor, testActivityComponent,
- mStack);
+ secondTask = new TaskBuilder(mService.mStackSupervisor).setStack(mStack).build();
// layout second task
assertEquals(RESULT_CONTINUE,
diff --git a/services/tests/servicestests/src/com/android/server/am/RecentTasksTest.java b/services/tests/servicestests/src/com/android/server/am/RecentTasksTest.java
index e607228..3c9b542 100644
--- a/services/tests/servicestests/src/com/android/server/am/RecentTasksTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/RecentTasksTest.java
@@ -16,44 +16,55 @@
package com.android.server.am;
+import static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.eq;
+import static org.junit.Assert.fail;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.when;
+import static java.lang.Integer.MAX_VALUE;
+
+import android.app.ActivityManager.RecentTaskInfo;
+import android.app.ActivityManager.RunningTaskInfo;
import android.content.ComponentName;
import android.content.Context;
+import android.content.pm.PackageManager;
+import android.content.pm.ParceledListSlice;
import android.content.pm.UserInfo;
-import android.os.Debug;
+import android.graphics.Rect;
+import android.os.Bundle;
+import android.os.Looper;
+import android.os.RemoteException;
import android.os.SystemClock;
import android.platform.test.annotations.Presubmit;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.MediumTest;
import android.support.test.runner.AndroidJUnit4;
import android.util.MutableLong;
+import android.util.SparseArray;
import android.util.SparseBooleanArray;
import com.android.server.am.RecentTasks.Callbacks;
-import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
/**
* runtest --path frameworks/base/services/tests/servicestests/src/com/android/server/am/RecentTasksTest.java
@@ -67,13 +78,17 @@
private static final int TEST_QUIET_USER_ID = 20;
private static final UserInfo DEFAULT_USER_INFO = new UserInfo();
private static final UserInfo QUIET_USER_INFO = new UserInfo();
+ private static final ComponentName MY_COMPONENT = new ComponentName(
+ RecentTasksTest.class.getPackage().getName(), RecentTasksTest.class.getName());
private static int LAST_TASK_ID = 1;
+ private static int INVALID_STACK_ID = 999;
private Context mContext = InstrumentationRegistry.getContext();
private ActivityManagerService mService;
private ActivityStack mStack;
private TestTaskPersister mTaskPersister;
private RecentTasks mRecentTasks;
+ private RunningTasks mRunningTasks;
private static ArrayList<TaskRecord> mTasks = new ArrayList<>();
private static ArrayList<TaskRecord> mSameDocumentTasks = new ArrayList<>();
@@ -91,6 +106,14 @@
}
@Override
+ Set<Integer> getProfileIds(int userId) {
+ Set<Integer> profileIds = new HashSet<>();
+ profileIds.add(TEST_USER_0_ID);
+ profileIds.add(TEST_QUIET_USER_ID);
+ return profileIds;
+ }
+
+ @Override
UserInfo getUserInfo(int userId) {
switch (userId) {
case TEST_USER_0_ID:
@@ -108,12 +131,12 @@
public void setUp() throws Exception {
super.setUp();
- mService = createActivityManagerService();
+ mTaskPersister = new TestTaskPersister(mContext.getFilesDir());
+ mService = setupActivityManagerService(new MyTestActivityManagerService(mContext));
+ mRecentTasks = mService.getRecentTasks();
+ mRecentTasks.loadParametersFromResources(mContext.getResources());
mStack = mService.mStackSupervisor.getDefaultDisplay().createStack(
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
- mTaskPersister = new TestTaskPersister(mContext.getFilesDir());
- mRecentTasks = new RecentTasks(mService, mTaskPersister, new TestUserController(mService));
- mRecentTasks.loadParametersFromResources(mContext.getResources());
mCallbacksRecorder = new CallbacksRecorder();
mRecentTasks.registerCallback(mCallbacksRecorder);
QUIET_USER_INFO.flags = UserInfo.FLAG_MANAGED_PROFILE | UserInfo.FLAG_QUIET_MODE;
@@ -322,6 +345,103 @@
assertTrimmed(mTasks.get(0), mTasks.get(1));
}
+ @Test
+ public void testNotRecentsComponent_denyApiAccess() throws Exception {
+ doReturn(PackageManager.PERMISSION_DENIED).when(mService).checkPermission(anyString(),
+ anyInt(), anyInt());
+
+ // Expect the following methods to fail due to recents component not being set
+ ((TestRecentTasks) mRecentTasks).setIsCallerRecentsOverride(
+ TestRecentTasks.DENY_THROW_SECURITY_EXCEPTION);
+ testRecentTasksApis(false /* expectNoSecurityException */);
+ // Don't throw for the following tests
+ ((TestRecentTasks) mRecentTasks).setIsCallerRecentsOverride(TestRecentTasks.DENY);
+ testGetTasksApis(false /* expectNoSecurityException */);
+ }
+
+ @Test
+ public void testRecentsComponent_allowApiAccessWithoutPermissions() throws Exception {
+ doReturn(PackageManager.PERMISSION_DENIED).when(mService).checkPermission(anyString(),
+ anyInt(), anyInt());
+
+ // Set the recents component and ensure that the following calls do not fail
+ ((TestRecentTasks) mRecentTasks).setIsCallerRecentsOverride(TestRecentTasks.GRANT);
+ testRecentTasksApis(true /* expectNoSecurityException */);
+ testGetTasksApis(true /* expectNoSecurityException */);
+ }
+
+ private void testRecentTasksApis(boolean expectCallable) {
+ assertSecurityException(expectCallable, () -> mService.removeStack(INVALID_STACK_ID));
+ assertSecurityException(expectCallable,
+ () -> mService.removeStacksInWindowingModes(new int[] {WINDOWING_MODE_UNDEFINED}));
+ assertSecurityException(expectCallable,
+ () -> mService.removeStacksWithActivityTypes(new int[] {ACTIVITY_TYPE_UNDEFINED}));
+ assertSecurityException(expectCallable, () -> mService.removeTask(0));
+ assertSecurityException(expectCallable,
+ () -> mService.setTaskWindowingMode(0, WINDOWING_MODE_UNDEFINED, true));
+ assertSecurityException(expectCallable,
+ () -> mService.moveTaskToStack(0, INVALID_STACK_ID, true));
+ assertSecurityException(expectCallable,
+ () -> mService.moveTaskToDockedStack(0, DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT, true,
+ true, new Rect()));
+ assertSecurityException(expectCallable, () -> mService.dismissSplitScreenMode(true));
+ assertSecurityException(expectCallable, () -> mService.dismissPip(true, 0));
+ assertSecurityException(expectCallable,
+ () -> mService.moveTopActivityToPinnedStack(INVALID_STACK_ID, new Rect()));
+ assertSecurityException(expectCallable,
+ () -> mService.resizeStack(INVALID_STACK_ID, new Rect(), true, true, true, 0));
+ assertSecurityException(expectCallable,
+ () -> mService.resizeDockedStack(new Rect(), new Rect(), new Rect(), new Rect(),
+ new Rect()));
+ assertSecurityException(expectCallable,
+ () -> mService.resizePinnedStack(new Rect(), new Rect()));
+ assertSecurityException(expectCallable, () -> mService.getAllStackInfos());
+ assertSecurityException(expectCallable,
+ () -> mService.getStackInfo(WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_UNDEFINED));
+ assertSecurityException(expectCallable, () -> {
+ try {
+ mService.getFocusedStackInfo();
+ } catch (RemoteException e) {
+ // Ignore
+ }
+ });
+ assertSecurityException(expectCallable,
+ () -> mService.moveTasksToFullscreenStack(INVALID_STACK_ID, true));
+ assertSecurityException(expectCallable,
+ () -> mService.startActivityFromRecents(0, new Bundle()));
+ assertSecurityException(expectCallable,
+ () -> mService.getTaskSnapshot(0, true));
+ assertSecurityException(expectCallable, () -> {
+ try {
+ mService.registerTaskStackListener(null);
+ } catch (RemoteException e) {
+ // Ignore
+ }
+ });
+ assertSecurityException(expectCallable, () -> {
+ try {
+ mService.unregisterTaskStackListener(null);
+ } catch (RemoteException e) {
+ // Ignore
+ }
+ });
+ assertSecurityException(expectCallable, () -> mService.getTaskDescription(0));
+ assertSecurityException(expectCallable, () -> mService.cancelTaskWindowTransition(0));
+ assertSecurityException(expectCallable, () -> mService.cancelTaskThumbnailTransition(0));
+ }
+
+ private void testGetTasksApis(boolean expectCallable) {
+ mService.getRecentTasks(MAX_VALUE, 0, TEST_USER_0_ID);
+ mService.getTasks(MAX_VALUE);
+ if (expectCallable) {
+ assertTrue(((TestRecentTasks) mRecentTasks).mLastAllowed);
+ assertTrue(((TestRunningTasks) mRunningTasks).mLastAllowed);
+ } else {
+ assertFalse(((TestRecentTasks) mRecentTasks).mLastAllowed);
+ assertFalse(((TestRunningTasks) mRunningTasks).mLastAllowed);
+ }
+ }
+
private ComponentName createComponent(String className) {
return new ComponentName(mContext.getPackageName(), className);
}
@@ -335,8 +455,9 @@
}
private TaskRecord createTask(String className, int flags, int userId) {
- TaskRecord task = createTask(mService.mStackSupervisor, createComponent(className), flags,
- LAST_TASK_ID++, mStack);
+ TaskRecord task = new TaskBuilder(mService.mStackSupervisor)
+ .setComponent(createComponent(className))
+ .setStack(mStack).setFlags(flags).setTaskId(LAST_TASK_ID++).build();
task.userId = userId;
task.touchActiveTime();
return task;
@@ -366,6 +487,55 @@
}
}
+ private void assertSecurityException(boolean expectCallable, Runnable runnable) {
+ boolean noSecurityException = true;
+ try {
+ runnable.run();
+ } catch (SecurityException se) {
+ noSecurityException = false;
+ } catch (Exception e) {
+ // We only care about SecurityExceptions, fall through here
+ e.printStackTrace();
+ }
+ if (noSecurityException != expectCallable) {
+ fail("Expected callable: " + expectCallable + " but got no security exception: "
+ + noSecurityException);
+ }
+ }
+
+ private class MyTestActivityManagerService extends TestActivityManagerService {
+ MyTestActivityManagerService(Context context) {
+ super(context);
+ }
+
+ @Override
+ protected ActivityStackSupervisor createStackSupervisor() {
+ return new MyTestActivityStackSupervisor(this, mHandlerThread.getLooper());
+ }
+
+ @Override
+ protected RecentTasks createRecentTasks() {
+ return new TestRecentTasks(this, mTaskPersister, new TestUserController(this));
+ }
+
+ @Override
+ public boolean isUserRunning(int userId, int flags) {
+ return true;
+ }
+ }
+
+ private class MyTestActivityStackSupervisor extends TestActivityStackSupervisor {
+ public MyTestActivityStackSupervisor(ActivityManagerService service, Looper looper) {
+ super(service, looper);
+ }
+
+ @Override
+ RunningTasks createRunningTasks() {
+ mRunningTasks = new TestRunningTasks();
+ return mRunningTasks;
+ }
+ }
+
private static class CallbacksRecorder implements Callbacks {
ArrayList<TaskRecord> added = new ArrayList<>();
ArrayList<TaskRecord> trimmed = new ArrayList<>();
@@ -416,4 +586,61 @@
return super.restoreTasksForUserLocked(userId, preaddedTasks);
}
}
+
+ private static class TestRecentTasks extends RecentTasks {
+ static final int GRANT = 0;
+ static final int DENY = 1;
+ static final int DENY_THROW_SECURITY_EXCEPTION = 2;
+
+ private boolean mOverrideIsCallerRecents;
+ private int mIsCallerRecentsPolicy;
+ boolean mLastAllowed;
+
+ TestRecentTasks(ActivityManagerService service, TaskPersister taskPersister,
+ UserController userController) {
+ super(service, taskPersister, userController);
+ }
+
+ @Override
+ boolean isCallerRecents(int callingUid) {
+ if (mOverrideIsCallerRecents) {
+ switch (mIsCallerRecentsPolicy) {
+ case GRANT:
+ return true;
+ case DENY:
+ return false;
+ case DENY_THROW_SECURITY_EXCEPTION:
+ throw new SecurityException();
+ }
+ }
+ return super.isCallerRecents(callingUid);
+ }
+
+ void setIsCallerRecentsOverride(int policy) {
+ mOverrideIsCallerRecents = true;
+ mIsCallerRecentsPolicy = policy;
+ }
+
+ @Override
+ ParceledListSlice<RecentTaskInfo> getRecentTasks(int maxNum, int flags,
+ boolean getTasksAllowed,
+ boolean getDetailedTasks, int userId, int callingUid) {
+ mLastAllowed = getTasksAllowed;
+ return super.getRecentTasks(maxNum, flags, getTasksAllowed, getDetailedTasks, userId,
+ callingUid);
+ }
+ }
+
+ private static class TestRunningTasks extends RunningTasks {
+ boolean mLastAllowed;
+
+ @Override
+ void getTasks(int maxNum, List<RunningTaskInfo> list, int ignoreActivityType,
+ int ignoreWindowingMode, SparseArray<ActivityDisplay> activityDisplays,
+ int callingUid, boolean allowed) {
+ mLastAllowed = allowed;
+ super.getTasks(maxNum, list, ignoreActivityType, ignoreWindowingMode, activityDisplays,
+ callingUid, allowed);
+ }
+ }
}
\ No newline at end of file
diff --git a/services/tests/servicestests/src/com/android/server/am/RunningTasksTest.java b/services/tests/servicestests/src/com/android/server/am/RunningTasksTest.java
new file mode 100644
index 0000000..fc75628
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/am/RunningTasksTest.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2017 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.am;
+
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+import static android.view.Display.DEFAULT_DISPLAY;
+
+import static com.android.server.am.ActivityDisplay.POSITION_BOTTOM;
+
+import static org.junit.Assert.assertTrue;
+
+import android.app.ActivityManager.RunningTaskInfo;
+import android.content.ComponentName;
+import android.content.Context;
+import android.platform.test.annotations.Presubmit;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.MediumTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.util.SparseArray;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.ArrayList;
+
+/**
+ * runtest --path frameworks/base/services/tests/servicestests/src/com/android/server/am/RunningTasksTest.java
+ */
+@MediumTest
+@Presubmit
+@RunWith(AndroidJUnit4.class)
+public class RunningTasksTest extends ActivityTestsBase {
+
+ private Context mContext = InstrumentationRegistry.getContext();
+ private ActivityManagerService mService;
+
+ private RunningTasks mRunningTasks;
+
+ @Before
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+
+ mService = createActivityManagerService();
+ mRunningTasks = new RunningTasks();
+ }
+
+ @Test
+ public void testCollectTasksByLastActiveTime() throws Exception {
+ // Create a number of stacks with tasks (of incrementing active time)
+ final ActivityStackSupervisor supervisor = mService.mStackSupervisor;
+ final SparseArray<ActivityDisplay> displays = new SparseArray<>();
+ final ActivityDisplay display = new ActivityDisplay(supervisor, DEFAULT_DISPLAY);
+ displays.put(DEFAULT_DISPLAY, display);
+
+ final int numStacks = 2;
+ for (int stackIndex = 0; stackIndex < numStacks; stackIndex++) {
+ final ActivityStack stack = new TestActivityStack(display, stackIndex, supervisor,
+ WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true);
+ display.addChild(stack, POSITION_BOTTOM);
+ }
+
+ final int numTasks = 10;
+ int activeTime = 0;
+ for (int i = 0; i < numTasks; i++) {
+ createTask(display.getChildAt(i % numStacks), ".Task" + i, i, activeTime++);
+ }
+
+ // Ensure that the latest tasks were returned in order of decreasing last active time,
+ // collected from all tasks across all the stacks
+ final int numFetchTasks = 5;
+ ArrayList<RunningTaskInfo> tasks = new ArrayList<>();
+ mRunningTasks.getTasks(5, tasks, ACTIVITY_TYPE_UNDEFINED, WINDOWING_MODE_UNDEFINED,
+ displays, -1 /* callingUid */, true /* allowed */);
+ assertTrue(tasks.size() == numFetchTasks);
+ for (int i = 0; i < numFetchTasks; i++) {
+ assertTrue(tasks.get(i).id == (numTasks - i - 1));
+ }
+
+ // Ensure that requesting more than the total number of tasks only returns the subset
+ // and does not crash
+ tasks.clear();
+ mRunningTasks.getTasks(100, tasks, ACTIVITY_TYPE_UNDEFINED, WINDOWING_MODE_UNDEFINED,
+ displays, -1 /* callingUid */, true /* allowed */);
+ assertTrue(tasks.size() == numTasks);
+ for (int i = 0; i < numTasks; i++) {
+ assertTrue(tasks.get(i).id == (numTasks - i - 1));
+ }
+ }
+
+ /**
+ * Create a task with a single activity in it, with the given last active time.
+ */
+ private TaskRecord createTask(ActivityStack stack, String className, int taskId,
+ int lastActiveTime) {
+ final TaskRecord task = new TaskBuilder(mService.mStackSupervisor)
+ .setComponent(new ComponentName(mContext.getPackageName(), className))
+ .setTaskId(taskId)
+ .setStack(stack)
+ .build();
+ task.lastActiveTime = lastActiveTime;
+ final ActivityRecord activity = new ActivityBuilder(mService)
+ .setTask(task)
+ .setComponent(new ComponentName(mContext.getPackageName(), ".TaskActivity"))
+ .build();
+ return task;
+ }
+}
\ No newline at end of file
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index c2cb66d..27a29b6 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -104,6 +104,8 @@
import com.android.internal.util.WakeupMessage;
import com.android.internal.util.test.BroadcastInterceptingContext;
import com.android.internal.util.test.FakeSettingsProvider;
+import com.android.server.connectivity.DefaultNetworkMetrics;
+import com.android.server.connectivity.IpConnectivityMetrics;
import com.android.server.connectivity.MockableSystemProperties;
import com.android.server.connectivity.NetworkAgentInfo;
import com.android.server.connectivity.NetworkMonitor;
@@ -156,6 +158,9 @@
private MockNetworkAgent mEthernetNetworkAgent;
private Context mContext;
+ @Mock IpConnectivityMetrics.Logger mMetricsService;
+ @Mock DefaultNetworkMetrics mDefaultNetworkMetrics;
+
// This class exists to test bindProcessToNetwork and getBoundNetworkForProcess. These methods
// do not go through ConnectivityService but talk to netd directly, so they don't automatically
// reflect the state of our test ConnectivityService.
@@ -805,6 +810,11 @@
return Context.ETHERNET_SERVICE.equals(name);
}
+ @Override
+ protected IpConnectivityMetrics.Logger metricsLogger() {
+ return mMetricsService;
+ }
+
public WrappedNetworkMonitor getLastCreatedWrappedNetworkMonitor() {
return mLastCreatedNetworkMonitor;
}
@@ -833,6 +843,9 @@
public void setUp() throws Exception {
mContext = InstrumentationRegistry.getContext();
+ MockitoAnnotations.initMocks(this);
+ when(mMetricsService.defaultNetworkMetrics()).thenReturn(mDefaultNetworkMetrics);
+
// InstrumentationTestRunner prepares a looper, but AndroidJUnitRunner does not.
// http://b/25897652 .
if (Looper.myLooper() == null) {
diff --git a/tests/net/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java b/tests/net/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java
index 2624176..ad6ebf9 100644
--- a/tests/net/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java
+++ b/tests/net/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java
@@ -198,21 +198,20 @@
@Test
public void testDefaultNetworkEventSerialization() {
- ConnectivityMetricsEvent ev = describeIpEvent(
- aType(DefaultNetworkEvent.class),
- anInt(102),
- anIntArray(1, 2, 3),
- anInt(101),
- aBool(true),
- aBool(false));
+ DefaultNetworkEvent ev = new DefaultNetworkEvent();
+ ev.netId = 102;
+ ev.prevNetId = 101;
+ ev.transportTypes = new int[]{1, 2, 3};
+ ev.prevIPv4 = true;
+ ev.prevIPv6 = true;
String want = String.join("\n",
"dropped_events: 0",
"events <",
" if_name: \"\"",
" link_layer: 0",
- " network_id: 0",
- " time_ms: 1",
+ " network_id: 102",
+ " time_ms: 0",
" transports: 0",
" default_network_event <",
" default_network_duration_ms: 0",
@@ -226,7 +225,7 @@
" previous_network_id <",
" network_id: 101",
" >",
- " previous_network_ip_support: 1",
+ " previous_network_ip_support: 3",
" transport_types: 1",
" transport_types: 2",
" transport_types: 3",
@@ -234,7 +233,7 @@
">",
"version: 2\n");
- verifySerialization(want, ev);
+ verifySerialization(want, IpConnectivityEventBuilder.toProto(ev));
}
@Test
diff --git a/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java b/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java
index a395c48..6c1decc 100644
--- a/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java
+++ b/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java
@@ -18,6 +18,7 @@
import static android.net.metrics.INetdEventListener.EVENT_GETADDRINFO;
import static android.net.metrics.INetdEventListener.EVENT_GETHOSTBYNAME;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -30,6 +31,10 @@
import android.net.ConnectivityManager;
import android.net.ConnectivityMetricsEvent;
import android.net.IIpConnectivityMetrics;
+import android.net.IpPrefix;
+import android.net.LinkAddress;
+import android.net.LinkProperties;
+import android.net.RouteInfo;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.metrics.ApfProgramEvent;
@@ -41,18 +46,22 @@
import android.net.metrics.IpReachabilityEvent;
import android.net.metrics.RaEvent;
import android.net.metrics.ValidationProbeEvent;
-import android.system.OsConstants;
import android.os.Parcelable;
import android.support.test.runner.AndroidJUnit4;
+import android.system.OsConstants;
import android.test.suitebuilder.annotation.SmallTest;
import android.util.Base64;
+
+import com.android.internal.util.BitUtils;
import com.android.server.connectivity.metrics.nano.IpConnectivityLogClass;
+
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
+
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@@ -162,6 +171,144 @@
}
@Test
+ public void testDefaultNetworkEvents() throws Exception {
+ final long cell = BitUtils.packBits(new int[]{NetworkCapabilities.TRANSPORT_CELLULAR});
+ final long wifi = BitUtils.packBits(new int[]{NetworkCapabilities.TRANSPORT_WIFI});
+
+ NetworkAgentInfo[][] defaultNetworks = {
+ // nothing -> cell
+ {null, makeNai(100, 10, false, true, cell)},
+ // cell -> wifi
+ {makeNai(100, 50, true, true, cell), makeNai(101, 20, true, false, wifi)},
+ // wifi -> nothing
+ {makeNai(101, 60, true, false, wifi), null},
+ // nothing -> cell
+ {null, makeNai(102, 10, true, true, cell)},
+ // cell -> wifi
+ {makeNai(102, 50, true, true, cell), makeNai(103, 20, true, false, wifi)},
+ };
+
+ for (NetworkAgentInfo[] pair : defaultNetworks) {
+ mService.mDefaultNetworkMetrics.logDefaultNetworkEvent(pair[1], pair[0]);
+ }
+
+ String want = String.join("\n",
+ "dropped_events: 0",
+ "events <",
+ " if_name: \"\"",
+ " link_layer: 0",
+ " network_id: 100",
+ " time_ms: 0",
+ " transports: 0",
+ " default_network_event <",
+ " default_network_duration_ms: 0",
+ " final_score: 0",
+ " initial_score: 0",
+ " ip_support: 0",
+ " network_id <",
+ " network_id: 100",
+ " >",
+ " no_default_network_duration_ms: 0",
+ " previous_network_id <",
+ " network_id: 0",
+ " >",
+ " previous_network_ip_support: 0",
+ " transport_types: 0",
+ " >",
+ ">",
+ "events <",
+ " if_name: \"\"",
+ " link_layer: 0",
+ " network_id: 101",
+ " time_ms: 0",
+ " transports: 0",
+ " default_network_event <",
+ " default_network_duration_ms: 0",
+ " final_score: 0",
+ " initial_score: 0",
+ " ip_support: 0",
+ " network_id <",
+ " network_id: 101",
+ " >",
+ " no_default_network_duration_ms: 0",
+ " previous_network_id <",
+ " network_id: 100",
+ " >",
+ " previous_network_ip_support: 3",
+ " transport_types: 1",
+ " >",
+ ">",
+ "events <",
+ " if_name: \"\"",
+ " link_layer: 0",
+ " network_id: 0",
+ " time_ms: 0",
+ " transports: 0",
+ " default_network_event <",
+ " default_network_duration_ms: 0",
+ " final_score: 0",
+ " initial_score: 0",
+ " ip_support: 0",
+ " network_id <",
+ " network_id: 0",
+ " >",
+ " no_default_network_duration_ms: 0",
+ " previous_network_id <",
+ " network_id: 101",
+ " >",
+ " previous_network_ip_support: 1",
+ " >",
+ ">",
+ "events <",
+ " if_name: \"\"",
+ " link_layer: 0",
+ " network_id: 102",
+ " time_ms: 0",
+ " transports: 0",
+ " default_network_event <",
+ " default_network_duration_ms: 0",
+ " final_score: 0",
+ " initial_score: 0",
+ " ip_support: 0",
+ " network_id <",
+ " network_id: 102",
+ " >",
+ " no_default_network_duration_ms: 0",
+ " previous_network_id <",
+ " network_id: 0",
+ " >",
+ " previous_network_ip_support: 0",
+ " transport_types: 0",
+ " >",
+ ">",
+ "events <",
+ " if_name: \"\"",
+ " link_layer: 0",
+ " network_id: 103",
+ " time_ms: 0",
+ " transports: 0",
+ " default_network_event <",
+ " default_network_duration_ms: 0",
+ " final_score: 0",
+ " initial_score: 0",
+ " ip_support: 0",
+ " network_id <",
+ " network_id: 103",
+ " >",
+ " no_default_network_duration_ms: 0",
+ " previous_network_id <",
+ " network_id: 102",
+ " >",
+ " previous_network_ip_support: 3",
+ " transport_types: 1",
+ " >",
+ ">",
+ "version: 2\n");
+
+ verifySerialization(want, getdump("flush"));
+ }
+
+ @Test
public void testEndToEndLogging() throws Exception {
// TODO: instead of comparing textpb to textpb, parse textpb and compare proto to proto.
IpConnectivityLog logger = new IpConnectivityLog(mService.impl);
@@ -194,7 +341,6 @@
Parcelable[] events = {
new IpReachabilityEvent(IpReachabilityEvent.NUD_FAILED),
new DhcpClientEvent("SomeState", 192),
- new DefaultNetworkEvent(102, new int[]{1,2,3}, 101, true, false),
new IpManagerEvent(IpManagerEvent.PROVISIONING_OK, 5678),
validationEv,
apfStats,
@@ -233,6 +379,13 @@
wakeupEvent("wlan0", 10008);
wakeupEvent("rmnet0", 1000);
+ final long cell = BitUtils.packBits(new int[]{NetworkCapabilities.TRANSPORT_CELLULAR});
+ final long wifi = BitUtils.packBits(new int[]{NetworkCapabilities.TRANSPORT_WIFI});
+ NetworkAgentInfo cellNai = makeNai(100, 50, false, true, cell);
+ NetworkAgentInfo wifiNai = makeNai(101, 60, true, false, wifi);
+ mService.mDefaultNetworkMetrics.logDefaultNetworkEvent(cellNai, null);
+ mService.mDefaultNetworkMetrics.logDefaultNetworkEvent(wifiNai, cellNai);
+
String want = String.join("\n",
"dropped_events: 0",
"events <",
@@ -264,30 +417,6 @@
" network_id: 0",
" time_ms: 300",
" transports: 0",
- " default_network_event <",
- " default_network_duration_ms: 0",
- " final_score: 0",
- " initial_score: 0",
- " ip_support: 0",
- " network_id <",
- " network_id: 102",
- " >",
- " no_default_network_duration_ms: 0",
- " previous_network_id <",
- " network_id: 101",
- " >",
- " previous_network_ip_support: 1",
- " transport_types: 1",
- " transport_types: 2",
- " transport_types: 3",
- " >",
- ">",
- "events <",
- " if_name: \"\"",
- " link_layer: 4",
- " network_id: 0",
- " time_ms: 400",
- " transports: 0",
" ip_provisioning_event <",
" event_type: 1",
" if_name: \"\"",
@@ -298,7 +427,7 @@
" if_name: \"\"",
" link_layer: 4",
" network_id: 0",
- " time_ms: 500",
+ " time_ms: 400",
" transports: 0",
" validation_probe_event <",
" latency_ms: 40730",
@@ -310,7 +439,7 @@
" if_name: \"\"",
" link_layer: 4",
" network_id: 0",
- " time_ms: 600",
+ " time_ms: 500",
" transports: 0",
" apf_statistics <",
" dropped_ras: 2",
@@ -331,7 +460,7 @@
" if_name: \"\"",
" link_layer: 4",
" network_id: 0",
- " time_ms: 700",
+ " time_ms: 600",
" transports: 0",
" ra_event <",
" dnssl_lifetime: -1",
@@ -344,6 +473,50 @@
">",
"events <",
" if_name: \"\"",
+ " link_layer: 0",
+ " network_id: 100",
+ " time_ms: 0",
+ " transports: 0",
+ " default_network_event <",
+ " default_network_duration_ms: 0",
+ " final_score: 0",
+ " initial_score: 0",
+ " ip_support: 0",
+ " network_id <",
+ " network_id: 100",
+ " >",
+ " no_default_network_duration_ms: 0",
+ " previous_network_id <",
+ " network_id: 0",
+ " >",
+ " previous_network_ip_support: 0",
+ " transport_types: 0",
+ " >",
+ ">",
+ "events <",
+ " if_name: \"\"",
+ " link_layer: 0",
+ " network_id: 101",
+ " time_ms: 0",
+ " transports: 0",
+ " default_network_event <",
+ " default_network_duration_ms: 0",
+ " final_score: 0",
+ " initial_score: 0",
+ " ip_support: 0",
+ " network_id <",
+ " network_id: 101",
+ " >",
+ " no_default_network_duration_ms: 0",
+ " previous_network_id <",
+ " network_id: 100",
+ " >",
+ " previous_network_ip_support: 2",
+ " transport_types: 1",
+ " >",
+ ">",
+ "events <",
+ " if_name: \"\"",
" link_layer: 4",
" network_id: 100",
" time_ms: 0",
@@ -471,6 +644,26 @@
mNetdListener.onWakeupEvent(prefix, uid, uid, 0);
}
+ NetworkAgentInfo makeNai(int netId, int score, boolean ipv4, boolean ipv6, long transports) {
+ NetworkAgentInfo nai = mock(NetworkAgentInfo.class);
+ when(nai.network()).thenReturn(new Network(netId));
+ when(nai.getCurrentScore()).thenReturn(score);
+ nai.linkProperties = new LinkProperties();
+ nai.networkCapabilities = new NetworkCapabilities();
+ for (int t : BitUtils.unpackBits(transports)) {
+ nai.networkCapabilities.addTransportType(t);
+ }
+ if (ipv4) {
+ nai.linkProperties.addLinkAddress(new LinkAddress("192.0.2.12/24"));
+ nai.linkProperties.addRoute(new RouteInfo(new IpPrefix("0.0.0.0/0")));
+ }
+ if (ipv6) {
+ nai.linkProperties.addLinkAddress(new LinkAddress("2001:db8:dead:beef:f00::a0/64"));
+ nai.linkProperties.addRoute(new RouteInfo(new IpPrefix("::/0")));
+ }
+ return nai;
+ }
+
List<ConnectivityMetricsEvent> verifyEvents(int n, int timeoutMs) throws Exception {
ArgumentCaptor<ConnectivityMetricsEvent> captor =
ArgumentCaptor.forClass(ConnectivityMetricsEvent.class);