Merge "Move Activity multi-window event logic out of the public methods" into nyc-dev
diff --git a/api/current.txt b/api/current.txt
index d380e70..e9d5c3d 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -6417,22 +6417,6 @@
field public static final android.os.Parcelable.Creator<android.app.usage.ConfigurationStats> CREATOR;
}
- public class DataUsagePolicy {
- field public final int networkType;
- field public final java.lang.String[] subscriberIds;
- field public final long thresholdInBytes;
- field public final int[] uids;
- }
-
- public static class DataUsagePolicy.Builder {
- ctor public DataUsagePolicy.Builder();
- method public android.app.usage.DataUsagePolicy.Builder addSubscriberId(java.lang.String);
- method public android.app.usage.DataUsagePolicy.Builder addUid(int);
- method public android.app.usage.DataUsagePolicy build();
- method public android.app.usage.DataUsagePolicy.Builder setNetworkType(int);
- method public android.app.usage.DataUsagePolicy.Builder setThreshold(long);
- }
-
public final class NetworkStats implements java.lang.AutoCloseable {
method public void close();
method public boolean getNextBucket(android.app.usage.NetworkStats.Bucket);
@@ -6457,8 +6441,7 @@
field public static final int STATE_ALL = -1; // 0xffffffff
field public static final int STATE_DEFAULT = 1; // 0x1
field public static final int STATE_FOREGROUND = 2; // 0x2
- field public static final int TAG_ALL = 0; // 0x0
- field public static final int TAG_ANY = -1; // 0xffffffff
+ field public static final int TAG_NONE = 0; // 0x0
field public static final int UID_ALL = -1; // 0xffffffff
field public static final int UID_REMOVED = -4; // 0xfffffffc
field public static final int UID_TETHERING = -5; // 0xfffffffb
@@ -6467,20 +6450,18 @@
public class NetworkStatsManager {
method public android.app.usage.NetworkStats queryDetails(int, java.lang.String, long, long) throws android.os.RemoteException, java.lang.SecurityException;
method public android.app.usage.NetworkStats queryDetailsForUid(int, java.lang.String, long, long, int) throws android.os.RemoteException, java.lang.SecurityException;
- method public android.app.usage.NetworkStats queryDetailsForUidTag(int, java.lang.String, long, long, int, int) throws android.os.RemoteException, java.lang.SecurityException;
+ method public android.app.usage.NetworkStats queryDetailsForUidTag(int, java.lang.String, long, long, int, int);
method public android.app.usage.NetworkStats querySummary(int, java.lang.String, long, long) throws android.os.RemoteException, java.lang.SecurityException;
- method public android.app.usage.NetworkStats querySummary(int, java.lang.String, long, long, boolean) throws android.os.RemoteException, java.lang.SecurityException;
method public android.app.usage.NetworkStats.Bucket querySummaryForDevice(int, java.lang.String, long, long) throws android.os.RemoteException, java.lang.SecurityException;
method public android.app.usage.NetworkStats.Bucket querySummaryForUser(int, java.lang.String, long, long) throws android.os.RemoteException, java.lang.SecurityException;
- method public android.app.usage.NetworkStats.Bucket querySummaryForUser(int, java.lang.String, long, long, boolean) throws android.os.RemoteException, java.lang.SecurityException;
- method public void registerDataUsageCallback(android.app.usage.DataUsagePolicy, android.app.usage.NetworkStatsManager.DataUsageCallback);
- method public void registerDataUsageCallback(android.app.usage.DataUsagePolicy, android.app.usage.NetworkStatsManager.DataUsageCallback, android.os.Handler);
- method public void unregisterDataUsageCallback(android.app.usage.NetworkStatsManager.DataUsageCallback);
+ method public void registerUsageCallback(int, java.lang.String, long, android.app.usage.NetworkStatsManager.UsageCallback);
+ method public void registerUsageCallback(int, java.lang.String, long, android.app.usage.NetworkStatsManager.UsageCallback, android.os.Handler);
+ method public void unregisterUsageCallback(android.app.usage.NetworkStatsManager.UsageCallback);
}
- public static class NetworkStatsManager.DataUsageCallback {
- ctor public NetworkStatsManager.DataUsageCallback();
- method public void onLimitReached();
+ public static abstract class NetworkStatsManager.UsageCallback {
+ ctor public NetworkStatsManager.UsageCallback();
+ method public abstract void onThresholdReached(int, java.lang.String);
}
public final class UsageEvents implements android.os.Parcelable {
@@ -23538,12 +23519,6 @@
method public int getUid();
}
- public final class DataUsageRequest implements android.os.Parcelable {
- method public int describeContents();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.net.DataUsageRequest> CREATOR;
- }
-
public class DhcpInfo implements android.os.Parcelable {
ctor public DhcpInfo();
method public int describeContents();
diff --git a/api/removed.txt b/api/removed.txt
index f9fce40..2673a82 100644
--- a/api/removed.txt
+++ b/api/removed.txt
@@ -17,6 +17,37 @@
}
+package android.app.usage {
+
+ public class DataUsagePolicy {
+ field public final int networkType;
+ field public final java.lang.String[] subscriberIds;
+ field public final long thresholdInBytes;
+ field public final int[] uids;
+ }
+
+ public static class DataUsagePolicy.Builder {
+ ctor public DataUsagePolicy.Builder();
+ method public android.app.usage.DataUsagePolicy.Builder addSubscriberId(java.lang.String);
+ method public android.app.usage.DataUsagePolicy.Builder addUid(int);
+ method public android.app.usage.DataUsagePolicy build();
+ method public android.app.usage.DataUsagePolicy.Builder setNetworkType(int);
+ method public android.app.usage.DataUsagePolicy.Builder setThreshold(long);
+ }
+
+ public class NetworkStatsManager {
+ method public void registerDataUsageCallback(android.app.usage.DataUsagePolicy, android.app.usage.NetworkStatsManager.DataUsageCallback, android.os.Handler);
+ method public void registerDataUsageCallback(android.app.usage.DataUsagePolicy, android.app.usage.NetworkStatsManager.UsageCallback, android.os.Handler);
+ method public void unregisterDataUsageCallback(android.app.usage.NetworkStatsManager.DataUsageCallback);
+ }
+
+ public static abstract class NetworkStatsManager.DataUsageCallback {
+ ctor public NetworkStatsManager.DataUsageCallback();
+ method public deprecated void onLimitReached();
+ }
+
+}
+
package android.content {
public abstract class Context {
diff --git a/api/system-current.txt b/api/system-current.txt
index dbbefbf..e5c88cc 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -6698,22 +6698,6 @@
field public static final android.os.Parcelable.Creator<android.app.usage.ConfigurationStats> CREATOR;
}
- public class DataUsagePolicy {
- field public final int networkType;
- field public final java.lang.String[] subscriberIds;
- field public final long thresholdInBytes;
- field public final int[] uids;
- }
-
- public static class DataUsagePolicy.Builder {
- ctor public DataUsagePolicy.Builder();
- method public android.app.usage.DataUsagePolicy.Builder addSubscriberId(java.lang.String);
- method public android.app.usage.DataUsagePolicy.Builder addUid(int);
- method public android.app.usage.DataUsagePolicy build();
- method public android.app.usage.DataUsagePolicy.Builder setNetworkType(int);
- method public android.app.usage.DataUsagePolicy.Builder setThreshold(long);
- }
-
public final class NetworkStats implements java.lang.AutoCloseable {
method public void close();
method public boolean getNextBucket(android.app.usage.NetworkStats.Bucket);
@@ -6738,8 +6722,7 @@
field public static final int STATE_ALL = -1; // 0xffffffff
field public static final int STATE_DEFAULT = 1; // 0x1
field public static final int STATE_FOREGROUND = 2; // 0x2
- field public static final int TAG_ALL = 0; // 0x0
- field public static final int TAG_ANY = -1; // 0xffffffff
+ field public static final int TAG_NONE = 0; // 0x0
field public static final int UID_ALL = -1; // 0xffffffff
field public static final int UID_REMOVED = -4; // 0xfffffffc
field public static final int UID_TETHERING = -5; // 0xfffffffb
@@ -6748,20 +6731,18 @@
public class NetworkStatsManager {
method public android.app.usage.NetworkStats queryDetails(int, java.lang.String, long, long) throws android.os.RemoteException, java.lang.SecurityException;
method public android.app.usage.NetworkStats queryDetailsForUid(int, java.lang.String, long, long, int) throws android.os.RemoteException, java.lang.SecurityException;
- method public android.app.usage.NetworkStats queryDetailsForUidTag(int, java.lang.String, long, long, int, int) throws android.os.RemoteException, java.lang.SecurityException;
+ method public android.app.usage.NetworkStats queryDetailsForUidTag(int, java.lang.String, long, long, int, int);
method public android.app.usage.NetworkStats querySummary(int, java.lang.String, long, long) throws android.os.RemoteException, java.lang.SecurityException;
- method public android.app.usage.NetworkStats querySummary(int, java.lang.String, long, long, boolean) throws android.os.RemoteException, java.lang.SecurityException;
method public android.app.usage.NetworkStats.Bucket querySummaryForDevice(int, java.lang.String, long, long) throws android.os.RemoteException, java.lang.SecurityException;
method public android.app.usage.NetworkStats.Bucket querySummaryForUser(int, java.lang.String, long, long) throws android.os.RemoteException, java.lang.SecurityException;
- method public android.app.usage.NetworkStats.Bucket querySummaryForUser(int, java.lang.String, long, long, boolean) throws android.os.RemoteException, java.lang.SecurityException;
- method public void registerDataUsageCallback(android.app.usage.DataUsagePolicy, android.app.usage.NetworkStatsManager.DataUsageCallback);
- method public void registerDataUsageCallback(android.app.usage.DataUsagePolicy, android.app.usage.NetworkStatsManager.DataUsageCallback, android.os.Handler);
- method public void unregisterDataUsageCallback(android.app.usage.NetworkStatsManager.DataUsageCallback);
+ method public void registerUsageCallback(int, java.lang.String, long, android.app.usage.NetworkStatsManager.UsageCallback);
+ method public void registerUsageCallback(int, java.lang.String, long, android.app.usage.NetworkStatsManager.UsageCallback, android.os.Handler);
+ method public void unregisterUsageCallback(android.app.usage.NetworkStatsManager.UsageCallback);
}
- public static class NetworkStatsManager.DataUsageCallback {
- ctor public NetworkStatsManager.DataUsageCallback();
- method public void onLimitReached();
+ public static abstract class NetworkStatsManager.UsageCallback {
+ ctor public NetworkStatsManager.UsageCallback();
+ method public abstract void onThresholdReached(int, java.lang.String);
}
public final class UsageEvents implements android.os.Parcelable {
@@ -25364,12 +25345,6 @@
method public int getUid();
}
- public final class DataUsageRequest implements android.os.Parcelable {
- method public int describeContents();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.net.DataUsageRequest> CREATOR;
- }
-
public class DhcpInfo implements android.os.Parcelable {
ctor public DhcpInfo();
method public int describeContents();
diff --git a/api/system-removed.txt b/api/system-removed.txt
index 6897ce0..7f2c2d6 100644
--- a/api/system-removed.txt
+++ b/api/system-removed.txt
@@ -15,6 +15,37 @@
}
+package android.app.usage {
+
+ public class DataUsagePolicy {
+ field public final int networkType;
+ field public final java.lang.String[] subscriberIds;
+ field public final long thresholdInBytes;
+ field public final int[] uids;
+ }
+
+ public static class DataUsagePolicy.Builder {
+ ctor public DataUsagePolicy.Builder();
+ method public android.app.usage.DataUsagePolicy.Builder addSubscriberId(java.lang.String);
+ method public android.app.usage.DataUsagePolicy.Builder addUid(int);
+ method public android.app.usage.DataUsagePolicy build();
+ method public android.app.usage.DataUsagePolicy.Builder setNetworkType(int);
+ method public android.app.usage.DataUsagePolicy.Builder setThreshold(long);
+ }
+
+ public class NetworkStatsManager {
+ method public void registerDataUsageCallback(android.app.usage.DataUsagePolicy, android.app.usage.NetworkStatsManager.DataUsageCallback, android.os.Handler);
+ method public void registerDataUsageCallback(android.app.usage.DataUsagePolicy, android.app.usage.NetworkStatsManager.UsageCallback, android.os.Handler);
+ method public void unregisterDataUsageCallback(android.app.usage.NetworkStatsManager.DataUsageCallback);
+ }
+
+ public static abstract class NetworkStatsManager.DataUsageCallback {
+ ctor public NetworkStatsManager.DataUsageCallback();
+ method public deprecated void onLimitReached();
+ }
+
+}
+
package android.content {
public abstract class Context {
diff --git a/api/test-current.txt b/api/test-current.txt
index acd7299..ff2a41c 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -6422,22 +6422,6 @@
field public static final android.os.Parcelable.Creator<android.app.usage.ConfigurationStats> CREATOR;
}
- public class DataUsagePolicy {
- field public final int networkType;
- field public final java.lang.String[] subscriberIds;
- field public final long thresholdInBytes;
- field public final int[] uids;
- }
-
- public static class DataUsagePolicy.Builder {
- ctor public DataUsagePolicy.Builder();
- method public android.app.usage.DataUsagePolicy.Builder addSubscriberId(java.lang.String);
- method public android.app.usage.DataUsagePolicy.Builder addUid(int);
- method public android.app.usage.DataUsagePolicy build();
- method public android.app.usage.DataUsagePolicy.Builder setNetworkType(int);
- method public android.app.usage.DataUsagePolicy.Builder setThreshold(long);
- }
-
public final class NetworkStats implements java.lang.AutoCloseable {
method public void close();
method public boolean getNextBucket(android.app.usage.NetworkStats.Bucket);
@@ -6462,8 +6446,7 @@
field public static final int STATE_ALL = -1; // 0xffffffff
field public static final int STATE_DEFAULT = 1; // 0x1
field public static final int STATE_FOREGROUND = 2; // 0x2
- field public static final int TAG_ALL = 0; // 0x0
- field public static final int TAG_ANY = -1; // 0xffffffff
+ field public static final int TAG_NONE = 0; // 0x0
field public static final int UID_ALL = -1; // 0xffffffff
field public static final int UID_REMOVED = -4; // 0xfffffffc
field public static final int UID_TETHERING = -5; // 0xfffffffb
@@ -6472,20 +6455,18 @@
public class NetworkStatsManager {
method public android.app.usage.NetworkStats queryDetails(int, java.lang.String, long, long) throws android.os.RemoteException, java.lang.SecurityException;
method public android.app.usage.NetworkStats queryDetailsForUid(int, java.lang.String, long, long, int) throws android.os.RemoteException, java.lang.SecurityException;
- method public android.app.usage.NetworkStats queryDetailsForUidTag(int, java.lang.String, long, long, int, int) throws android.os.RemoteException, java.lang.SecurityException;
+ method public android.app.usage.NetworkStats queryDetailsForUidTag(int, java.lang.String, long, long, int, int);
method public android.app.usage.NetworkStats querySummary(int, java.lang.String, long, long) throws android.os.RemoteException, java.lang.SecurityException;
- method public android.app.usage.NetworkStats querySummary(int, java.lang.String, long, long, boolean) throws android.os.RemoteException, java.lang.SecurityException;
method public android.app.usage.NetworkStats.Bucket querySummaryForDevice(int, java.lang.String, long, long) throws android.os.RemoteException, java.lang.SecurityException;
method public android.app.usage.NetworkStats.Bucket querySummaryForUser(int, java.lang.String, long, long) throws android.os.RemoteException, java.lang.SecurityException;
- method public android.app.usage.NetworkStats.Bucket querySummaryForUser(int, java.lang.String, long, long, boolean) throws android.os.RemoteException, java.lang.SecurityException;
- method public void registerDataUsageCallback(android.app.usage.DataUsagePolicy, android.app.usage.NetworkStatsManager.DataUsageCallback);
- method public void registerDataUsageCallback(android.app.usage.DataUsagePolicy, android.app.usage.NetworkStatsManager.DataUsageCallback, android.os.Handler);
- method public void unregisterDataUsageCallback(android.app.usage.NetworkStatsManager.DataUsageCallback);
+ method public void registerUsageCallback(int, java.lang.String, long, android.app.usage.NetworkStatsManager.UsageCallback);
+ method public void registerUsageCallback(int, java.lang.String, long, android.app.usage.NetworkStatsManager.UsageCallback, android.os.Handler);
+ method public void unregisterUsageCallback(android.app.usage.NetworkStatsManager.UsageCallback);
}
- public static class NetworkStatsManager.DataUsageCallback {
- ctor public NetworkStatsManager.DataUsageCallback();
- method public void onLimitReached();
+ public static abstract class NetworkStatsManager.UsageCallback {
+ ctor public NetworkStatsManager.UsageCallback();
+ method public abstract void onThresholdReached(int, java.lang.String);
}
public final class UsageEvents implements android.os.Parcelable {
@@ -23607,12 +23588,6 @@
method public int getUid();
}
- public final class DataUsageRequest implements android.os.Parcelable {
- method public int describeContents();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.net.DataUsageRequest> CREATOR;
- }
-
public class DhcpInfo implements android.os.Parcelable {
ctor public DhcpInfo();
method public int describeContents();
diff --git a/api/test-removed.txt b/api/test-removed.txt
index f9fce40..2673a82 100644
--- a/api/test-removed.txt
+++ b/api/test-removed.txt
@@ -17,6 +17,37 @@
}
+package android.app.usage {
+
+ public class DataUsagePolicy {
+ field public final int networkType;
+ field public final java.lang.String[] subscriberIds;
+ field public final long thresholdInBytes;
+ field public final int[] uids;
+ }
+
+ public static class DataUsagePolicy.Builder {
+ ctor public DataUsagePolicy.Builder();
+ method public android.app.usage.DataUsagePolicy.Builder addSubscriberId(java.lang.String);
+ method public android.app.usage.DataUsagePolicy.Builder addUid(int);
+ method public android.app.usage.DataUsagePolicy build();
+ method public android.app.usage.DataUsagePolicy.Builder setNetworkType(int);
+ method public android.app.usage.DataUsagePolicy.Builder setThreshold(long);
+ }
+
+ public class NetworkStatsManager {
+ method public void registerDataUsageCallback(android.app.usage.DataUsagePolicy, android.app.usage.NetworkStatsManager.DataUsageCallback, android.os.Handler);
+ method public void registerDataUsageCallback(android.app.usage.DataUsagePolicy, android.app.usage.NetworkStatsManager.UsageCallback, android.os.Handler);
+ method public void unregisterDataUsageCallback(android.app.usage.NetworkStatsManager.DataUsageCallback);
+ }
+
+ public static abstract class NetworkStatsManager.DataUsageCallback {
+ ctor public NetworkStatsManager.DataUsageCallback();
+ method public deprecated void onLimitReached();
+ }
+
+}
+
package android.content {
public abstract class Context {
diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java
index 8b277b2..ae78e218 100644
--- a/core/java/android/accessibilityservice/AccessibilityService.java
+++ b/core/java/android/accessibilityservice/AccessibilityService.java
@@ -949,7 +949,7 @@
mService.mConnectionId);
if (connection != null) {
try {
- return connection.getMagnifiedRegion();
+ return connection.getMagnificationRegion();
} catch (RemoteException re) {
Log.w(LOG_TAG, "Failed to obtain magnified region", re);
re.rethrowFromSystemServer();
diff --git a/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl b/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl
index 3783fca..7a55079 100644
--- a/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl
+++ b/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl
@@ -75,7 +75,7 @@
float getMagnificationCenterY();
- Region getMagnifiedRegion();
+ Region getMagnificationRegion();
boolean resetMagnification(boolean animate);
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index ff8cf66..8a92b54 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -901,7 +901,7 @@
*/
static public int getMaxRecentTasksStatic() {
if (gMaxRecentTasks < 0) {
- return gMaxRecentTasks = isLowRamDeviceStatic() ? 50 : 100;
+ return gMaxRecentTasks = isLowRamDeviceStatic() ? 36 : 48;
}
return gMaxRecentTasks;
}
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index f78f121..7105e4d 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -557,8 +557,9 @@
return;
}
try {
+ int bufferSize = SystemProperties.getInt("debug.traceview-buffer-size-mb", 8);
VMDebug.startMethodTracing(profileFile, profileFd.getFileDescriptor(),
- 8 * 1024 * 1024, 0, samplingInterval != 0, samplingInterval);
+ bufferSize * 1024 * 1024, 0, samplingInterval != 0, samplingInterval);
profiling = true;
} catch (RuntimeException e) {
Slog.w(TAG, "Profiling failed on path " + profileFile);
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index e60712a..752dc1e 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -466,11 +466,7 @@
final boolean isBundledApp = mApplicationInfo.isSystemApp()
&& !mApplicationInfo.isUpdatedSystemApp();
- // Apps are allowed to open any native library under /data
- // TODO (dimitry):This is something which could be limited to apps own directory
- // later on but currently there are number of apps relying on this.
- // (see http://b/27588281 and http://b/26954419 for examples)
- String libraryPermittedPath = "/data";
+ String libraryPermittedPath = mDataDir;
if (isBundledApp) {
// This is necessary to grant bundled apps access to
// libraries located in subdirectories of /system/lib
diff --git a/core/java/android/app/usage/DataUsagePolicy.java b/core/java/android/app/usage/DataUsagePolicy.java
index 5a5dcbc..ee6b60c 100644
--- a/core/java/android/app/usage/DataUsagePolicy.java
+++ b/core/java/android/app/usage/DataUsagePolicy.java
@@ -29,6 +29,7 @@
/**
* Defines a policy for data usage callbacks, made through {@link DataUsagePolicy.Builder} and used
* to be notified on data usage via {@link NetworkStatsManager#registerDataUsageCallback}.
+ * @removed
*/
public class DataUsagePolicy {
diff --git a/core/java/android/app/usage/NetworkStats.java b/core/java/android/app/usage/NetworkStats.java
index 9963eab..226aa8f 100644
--- a/core/java/android/app/usage/NetworkStats.java
+++ b/core/java/android/app/usage/NetworkStats.java
@@ -193,14 +193,9 @@
public static final int ROAMING_YES = 0x2;
/**
- * Special TAG value matching any tag.
- */
- public static final int TAG_ANY = android.net.NetworkStats.TAG_ALL;
-
- /**
* Special TAG value for total data across all tags
*/
- public static final int TAG_ALL = android.net.NetworkStats.TAG_NONE;
+ public static final int TAG_NONE = android.net.NetworkStats.TAG_NONE;
private int mUid;
private int mTag;
@@ -232,8 +227,7 @@
private static int convertTag(int tag) {
switch (tag) {
- case android.net.NetworkStats.TAG_ALL: return TAG_ANY;
- case android.net.NetworkStats.TAG_NONE: return TAG_ALL;
+ case android.net.NetworkStats.TAG_NONE: return TAG_NONE;
}
return tag;
}
@@ -417,9 +411,9 @@
* Collects summary results and sets summary enumeration mode.
* @throws RemoteException
*/
- void startSummaryEnumeration(boolean includeTags) throws RemoteException {
+ void startSummaryEnumeration() throws RemoteException {
mSummary = mSession.getSummaryForAllUid(mTemplate, mStartTimeStamp, mEndTimeStamp,
- includeTags);
+ false /* includeTags */);
mEnumerationIndex = 0;
}
diff --git a/core/java/android/app/usage/NetworkStatsManager.java b/core/java/android/app/usage/NetworkStatsManager.java
index 2e3aca4..4a28117 100644
--- a/core/java/android/app/usage/NetworkStatsManager.java
+++ b/core/java/android/app/usage/NetworkStatsManager.java
@@ -106,7 +106,7 @@
* device. Result is a single Bucket aggregated over time, state, uid, tag and roaming. This
* means the bucket's start and end timestamp are going to be the same as the 'startTime' and
* 'endTime' parameters. State is going to be {@link NetworkStats.Bucket#STATE_ALL}, uid
- * {@link NetworkStats.Bucket#UID_ALL}, tag {@link NetworkStats.Bucket#TAG_ALL}
+ * {@link NetworkStats.Bucket#UID_ALL}, tag {@link NetworkStats.Bucket#TAG_NONE}
* and roaming {@link NetworkStats.Bucket#ROAMING_ALL}.
*
* @param networkType As defined in {@link ConnectivityManager}, e.g.
@@ -122,8 +122,11 @@
*/
public Bucket querySummaryForDevice(int networkType, String subscriberId,
long startTime, long endTime) throws SecurityException, RemoteException {
- NetworkTemplate template = createTemplate(networkType, subscriberId);
- if (template == null) {
+ NetworkTemplate template;
+ try {
+ template = createTemplate(networkType, subscriberId);
+ } catch (IllegalArgumentException e) {
+ if (DBG) Log.e(TAG, "Cannot create template", e);
return null;
}
@@ -136,21 +139,10 @@
}
/**
- * Query network usage statistics summaries aggregated across tags.
- *
- * #see querySummaryForUser(int, String, long, long, boolean)
- */
- public Bucket querySummaryForUser(int networkType, String subscriberId, long startTime,
- long endTime) throws SecurityException, RemoteException {
- return querySummaryForUser(networkType, subscriberId, startTime, endTime,
- false /* includeTags */);
- }
-
- /**
* Query network usage statistics summaries. Result is summarised data usage for all uids
* belonging to calling user. Result is a single Bucket aggregated over time, state and uid.
* This means the bucket's start and end timestamp are going to be the same as the 'startTime'
- * and 'endTime' parameters. State is going to be {@link NetworkStats.Bucket#STATE_ALL} and uid
+ * and 'endTime' parameters, state is going to be {@link NetworkStats.Bucket#STATE_ALL} and uid
* {@link NetworkStats.Bucket#UID_ALL}.
*
* @param networkType As defined in {@link ConnectivityManager}, e.g.
@@ -161,42 +153,33 @@
* {@link java.lang.System#currentTimeMillis}.
* @param endTime End of period. Defined in terms of "Unix time", see
* {@link java.lang.System#currentTimeMillis}.
- * @param includeTags whether to include network tags. If {@code true}, tags will be returned
- * and history retention may be shorter.
* @return Bucket object or null if permissions are insufficient or error happened during
* statistics collection.
*/
public Bucket querySummaryForUser(int networkType, String subscriberId, long startTime,
- long endTime, boolean includeTags) throws SecurityException, RemoteException {
- NetworkTemplate template = createTemplate(networkType, subscriberId);
- if (template == null) {
+ long endTime) throws SecurityException, RemoteException {
+ NetworkTemplate template;
+ try {
+ template = createTemplate(networkType, subscriberId);
+ } catch (IllegalArgumentException e) {
+ if (DBG) Log.e(TAG, "Cannot create template", e);
return null;
}
NetworkStats stats;
stats = new NetworkStats(mContext, template, startTime, endTime);
- stats.startSummaryEnumeration(includeTags);
+ stats.startSummaryEnumeration();
stats.close();
return stats.getSummaryAggregate();
}
/**
- * Query network usage statistics summaries aggregated across tags.
- *
- * #see querySummary(int, String, long, long, boolean)
- */
- public NetworkStats querySummary(int networkType, String subscriberId, long startTime,
- long endTime) throws SecurityException, RemoteException {
- return querySummary(networkType, subscriberId, startTime, endTime, false /* includeTags */);
- }
-
- /**
* Query network usage statistics summaries. Result filtered to include only uids belonging to
* calling user. Result is aggregated over time, hence all buckets will have the same start and
- * end timestamps. Not aggregated over state or uid or tag. This means buckets' start and end
- * timestamps are going to be the same as the 'startTime' and 'endTime' parameters. State,
- * uid and tag are going to vary.
+ * end timestamps. Not aggregated over state or uid. This means buckets' start and end
+ * timestamps are going to be the same as the 'startTime' and 'endTime' parameters.
+ * State and uid are going to vary, and tag is going to be the same.
*
* @param networkType As defined in {@link ConnectivityManager}, e.g.
* {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI}
@@ -206,21 +189,22 @@
* {@link java.lang.System#currentTimeMillis}.
* @param endTime End of period. Defined in terms of "Unix time", see
* {@link java.lang.System#currentTimeMillis}.
- * @param includeTags whether to include network tags. If {@code true}, tags will be returned
- * and history retention may be shorter.
* @return Statistics object or null if permissions are insufficient or error happened during
* statistics collection.
*/
public NetworkStats querySummary(int networkType, String subscriberId, long startTime,
- long endTime, boolean includeTags) throws SecurityException, RemoteException {
- NetworkTemplate template = createTemplate(networkType, subscriberId);
- if (template == null) {
+ long endTime) throws SecurityException, RemoteException {
+ NetworkTemplate template;
+ try {
+ template = createTemplate(networkType, subscriberId);
+ } catch (IllegalArgumentException e) {
+ if (DBG) Log.e(TAG, "Cannot create template", e);
return null;
}
NetworkStats result;
result = new NetworkStats(mContext, template, startTime, endTime);
- result.startSummaryEnumeration(includeTags);
+ result.startSummaryEnumeration();
return result;
}
@@ -233,7 +217,7 @@
public NetworkStats queryDetailsForUid(int networkType, String subscriberId,
long startTime, long endTime, int uid) throws SecurityException, RemoteException {
return queryDetailsForUidTag(networkType, subscriberId, startTime, endTime, uid,
- NetworkStats.Bucket.TAG_ALL);
+ NetworkStats.Bucket.TAG_NONE);
}
/**
@@ -255,22 +239,28 @@
* @param endTime End of period. Defined in terms of "Unix time", see
* {@link java.lang.System#currentTimeMillis}.
* @param uid UID of app
- * @param tag TAG of interest. Use {@link NetworkStats.Bucket#TAG_ANY} for any tags, use
- * {@link NetworkStats.Bucket#TAG_ALL} to aggregate over tags.
+ * @param tag TAG of interest. Use {@link NetworkStats.Bucket#TAG_NONE} for no tags.
* @return Statistics object or null if permissions are insufficient or error happened during
* statistics collection.
*/
public NetworkStats queryDetailsForUidTag(int networkType, String subscriberId,
- long startTime, long endTime, int uid, int tag) throws SecurityException,
- RemoteException {
- NetworkTemplate template = createTemplate(networkType, subscriberId);
- if (template == null) {
+ long startTime, long endTime, int uid, int tag) {
+ NetworkTemplate template;
+ try {
+ template = createTemplate(networkType, subscriberId);
+ } catch (IllegalArgumentException e) {
+ if (DBG) Log.e(TAG, "Cannot create template", e);
return null;
}
NetworkStats result;
- result = new NetworkStats(mContext, template, startTime, endTime);
- result.startHistoryEnumeration(uid, tag);
+ try {
+ result = new NetworkStats(mContext, template, startTime, endTime);
+ result.startHistoryEnumeration(uid, tag);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error while querying stats for uid=" + uid + " tag=" + tag, e);
+ return null;
+ }
return result;
}
@@ -280,7 +270,7 @@
* calling user. Result is aggregated over state but not aggregated over time or uid. This means
* buckets' start and end timestamps are going to be between 'startTime' and 'endTime'
* parameters. State is going to be {@link NetworkStats.Bucket#STATE_ALL}, uid will vary,
- * tag {@link NetworkStats.Bucket#TAG_ALL} and roaming is going to be
+ * tag {@link NetworkStats.Bucket#TAG_NONE} and roaming is going to be
* {@link NetworkStats.Bucket#ROAMING_ALL}.
* <p>Only includes buckets that atomically occur in the inclusive time range. Doesn't
* interpolate across partial buckets. Since bucket length is in the order of hours, this
@@ -299,44 +289,59 @@
*/
public NetworkStats queryDetails(int networkType, String subscriberId, long startTime,
long endTime) throws SecurityException, RemoteException {
- NetworkTemplate template = createTemplate(networkType, subscriberId);
- if (template == null) {
+ NetworkTemplate template;
+ try {
+ template = createTemplate(networkType, subscriberId);
+ } catch (IllegalArgumentException e) {
+ if (DBG) Log.e(TAG, "Cannot create template", e);
return null;
}
+
NetworkStats result;
result = new NetworkStats(mContext, template, startTime, endTime);
result.startUserUidEnumeration();
return result;
}
+ /** @removed */
+ public void registerDataUsageCallback(DataUsagePolicy policy, DataUsageCallback callback,
+ @Nullable Handler handler) {}
+
+ /** @removed */
+ public void registerDataUsageCallback(DataUsagePolicy policy, UsageCallback callback,
+ @Nullable Handler handler) {}
+
+ /** @removed */
+ public void unregisterDataUsageCallback(DataUsageCallback callback) {}
+
/**
- * Registers to receive notifications about data usage on specified networks and uids.
- * The callbacks will continue to be called as long as the process is live or
- * {@link #unregisterDataUsageCallback} is called.
+ * Registers to receive notifications about data usage on specified networks.
*
- * @param policy {@link DataUsagePolicy} describing this request.
- * @param callback The {@link DataUsageCallback} that the system will call when data usage
- * has exceeded the specified threshold.
+ * #see registerUsageCallback(int, String[], long, UsageCallback, Handler)
*/
- public void registerDataUsageCallback(DataUsagePolicy policy, DataUsageCallback callback) {
- registerDataUsageCallback(policy, callback, null /* handler */);
+ public void registerUsageCallback(int networkType, String subscriberId, long thresholdBytes,
+ UsageCallback callback) {
+ registerUsageCallback(networkType, subscriberId, thresholdBytes, null /* handler */);
}
/**
- * Registers to receive notifications about data usage on specified networks and uids.
- * The callbacks will continue to be called as long as the process is live or
- * {@link #unregisterDataUsageCallback} is called.
+ * Registers to receive notifications about data usage on specified networks.
*
- * @param policy {@link DataUsagePolicy} describing this request.
- * @param callback The {@link DataUsageCallback} that the system will call when data usage
+ * <p>The callbacks will continue to be called as long as the process is live or
+ * {@link #unregisterUsageCallback} is called.
+ *
+ * @param networkType Type of network to monitor. Either
+ {@link ConnectivityManager#TYPE_MOBILE} or {@link ConnectivityManager#TYPE_WIFI}.
+ * @param subscriberId If applicable, the subscriber id of the network interface.
+ * @param thresholdBytes Threshold in bytes to be notified on.
+ * @param callback The {@link UsageCallback} that the system will call when data usage
* has exceeded the specified threshold.
* @param handler to dispatch callback events through, otherwise if {@code null} it uses
* the calling thread.
*/
- public void registerDataUsageCallback(DataUsagePolicy policy, DataUsageCallback callback,
- @Nullable Handler handler) {
- checkNotNull(policy, "DataUsagePolicy cannot be null");
- checkNotNull(callback, "DataUsageCallback cannot be null");
+ public void registerUsageCallback(int networkType, String subscriberId, long thresholdBytes,
+ UsageCallback callback, @Nullable Handler handler) {
+ checkNotNull(callback, "UsageCallback cannot be null");
final Looper looper;
if (handler == null) {
@@ -345,62 +350,72 @@
looper = handler.getLooper();
}
- if (DBG) Log.d(TAG, "registerDataUsageCallback called with " + policy);
-
- NetworkTemplate[] templates;
- if (policy.subscriberIds == null || policy.subscriberIds.length == 0) {
- templates = new NetworkTemplate[1];
- templates[0] = createTemplate(policy.networkType, null /* subscriberId */);
- } else {
- templates = new NetworkTemplate[policy.subscriberIds.length];
- for (int i = 0; i < policy.subscriberIds.length; i++) {
- templates[i] = createTemplate(policy.networkType, policy.subscriberIds[i]);
- }
+ if (DBG) {
+ Log.d(TAG, "registerUsageCallback called with: {"
+ + " networkType=" + networkType
+ + " subscriberId=" + subscriberId
+ + " thresholdBytes=" + thresholdBytes
+ + " }");
}
+
+ NetworkTemplate template = createTemplate(networkType, subscriberId);
DataUsageRequest request = new DataUsageRequest(DataUsageRequest.REQUEST_ID_UNSET,
- templates, policy.uids, policy.thresholdInBytes);
+ template, thresholdBytes);
try {
- CallbackHandler callbackHandler = new CallbackHandler(looper, callback);
- callback.request = mService.registerDataUsageCallback(
+ CallbackHandler callbackHandler = new CallbackHandler(looper, networkType,
+ subscriberId, callback);
+ callback.request = mService.registerUsageCallback(
mContext.getOpPackageName(), request, new Messenger(callbackHandler),
new Binder());
- if (DBG) Log.d(TAG, "registerDataUsageCallback returned " + callback.request);
+ if (DBG) Log.d(TAG, "registerUsageCallback returned " + callback.request);
if (callback.request == null) {
Log.e(TAG, "Request from callback is null; should not happen");
}
} catch (RemoteException e) {
if (DBG) Log.d(TAG, "Remote exception when registering callback");
+ throw e.rethrowFromSystemServer();
}
}
/**
* Unregisters callbacks on data usage.
*
- * @param callback The {@link DataUsageCallback} used when registering.
+ * @param callback The {@link UsageCallback} used when registering.
*/
- public void unregisterDataUsageCallback(DataUsageCallback callback) {
+ public void unregisterUsageCallback(UsageCallback callback) {
if (callback == null || callback.request == null
|| callback.request.requestId == DataUsageRequest.REQUEST_ID_UNSET) {
- throw new IllegalArgumentException("Invalid DataUsageCallback");
+ throw new IllegalArgumentException("Invalid UsageCallback");
}
try {
- mService.unregisterDataUsageRequest(callback.request);
+ mService.unregisterUsageRequest(callback.request);
} catch (RemoteException e) {
if (DBG) Log.d(TAG, "Remote exception when unregistering callback");
+ throw e.rethrowFromSystemServer();
}
}
- /**
- * Base class for data usage callbacks. Should be extended by applications wanting
- * notifications.
- */
- public static class DataUsageCallback {
- /**
- * Called when data usage has reached the given policy threshold.
- */
+ /** @removed */
+ public static abstract class DataUsageCallback {
+ /** @removed */
+ @Deprecated
public void onLimitReached() {}
+ }
+ /**
+ * Base class for usage callbacks. Should be extended by applications wanting notifications.
+ */
+ public static abstract class UsageCallback {
+
+ /**
+ * Called when data usage has reached the given threshold.
+ */
+ public abstract void onThresholdReached(int networkType, String subscriberId);
+
+ /**
+ * @hide used for internal bookkeeping
+ */
private DataUsageRequest request;
}
@@ -414,18 +429,24 @@
template = NetworkTemplate.buildTemplateWifiWildcard();
} break;
default: {
- Log.w(TAG, "Cannot create template for network type " + networkType
- + ", subscriberId '" + NetworkIdentity.scrubSubscriberId(subscriberId) +
- "'.");
+ throw new IllegalArgumentException("Cannot create template for network type "
+ + networkType + ", subscriberId '"
+ + NetworkIdentity.scrubSubscriberId(subscriberId) + "'.");
}
}
return template;
}
private static class CallbackHandler extends Handler {
- private DataUsageCallback mCallback;
- CallbackHandler(Looper looper, DataUsageCallback callback) {
+ private final int mNetworkType;
+ private final String mSubscriberId;
+ private UsageCallback mCallback;
+
+ CallbackHandler(Looper looper, int networkType, String subscriberId,
+ UsageCallback callback) {
super(looper);
+ mNetworkType = networkType;
+ mSubscriberId = subscriberId;
mCallback = callback;
}
@@ -437,7 +458,7 @@
switch (message.what) {
case CALLBACK_LIMIT_REACHED: {
if (mCallback != null) {
- mCallback.onLimitReached();
+ mCallback.onThresholdReached(mNetworkType, mSubscriberId);
} else {
Log.e(TAG, "limit reached with released callback for " + request);
}
diff --git a/core/java/android/net/DataUsageRequest.java b/core/java/android/net/DataUsageRequest.java
index 8526584..ac9a5a3 100644
--- a/core/java/android/net/DataUsageRequest.java
+++ b/core/java/android/net/DataUsageRequest.java
@@ -20,7 +20,6 @@
import android.os.Parcel;
import android.os.Parcelable;
-import java.util.Arrays;
import java.util.Objects;
/**
@@ -28,56 +27,33 @@
* {@link android.app.usage.NetworkStatsManager#registerDataUsageCallback}.
* If no {@code uid}s are set, callbacks are restricted to device-owners,
* carrier-privileged apps, or system apps.
+ *
+ * @hide
*/
public final class DataUsageRequest implements Parcelable {
- /**
- * @hide
- */
public static final String PARCELABLE_KEY = "DataUsageRequest";
-
- /**
- * @hide
- */
public static final int REQUEST_ID_UNSET = 0;
/**
* Identifies the request. {@link DataUsageRequest}s should only be constructed by
* the Framework and it is used internally to identify the request.
- * @hide
*/
public final int requestId;
/**
- * Set of {@link NetworkTemplate}s describing the networks to monitor.
- * @hide
+ * {@link NetworkTemplate} describing the network to monitor.
*/
- public final NetworkTemplate[] templates;
-
- /**
- * Set of UIDs of which to monitor data usage.
- *
- * <p>If not {@code null}, the caller will be notified when any of the uids exceed
- * the given threshold. If {@code null} all uids for which the calling process has access
- * to stats will be monitored.
- * @hide
- */
- public final int[] uids;
+ public final NetworkTemplate template;
/**
* Threshold in bytes to be notified on.
- * @hide
*/
public final long thresholdInBytes;
- /**
- * @hide
- */
- public DataUsageRequest(int requestId, NetworkTemplate[] templates, int[] uids,
- long thresholdInBytes) {
+ public DataUsageRequest(int requestId, NetworkTemplate template, long thresholdInBytes) {
this.requestId = requestId;
- this.templates = templates;
- this.uids = uids;
+ this.template = template;
this.thresholdInBytes = thresholdInBytes;
}
@@ -89,8 +65,7 @@
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(requestId);
- dest.writeTypedArray(templates, flags);
- dest.writeIntArray(uids);
+ dest.writeParcelable(template, flags);
dest.writeLong(thresholdInBytes);
}
@@ -99,11 +74,10 @@
@Override
public DataUsageRequest createFromParcel(Parcel in) {
int requestId = in.readInt();
- NetworkTemplate[] templates = in.createTypedArray(NetworkTemplate.CREATOR);
- int[] uids = in.createIntArray();
+ NetworkTemplate template = in.readParcelable(null);
long thresholdInBytes = in.readLong();
- DataUsageRequest result = new DataUsageRequest(requestId,
- templates, uids, thresholdInBytes);
+ DataUsageRequest result = new DataUsageRequest(requestId, template,
+ thresholdInBytes);
return result;
}
@@ -116,8 +90,7 @@
@Override
public String toString() {
return "DataUsageRequest [ requestId=" + requestId
- + ", networkTemplates=" + Arrays.toString(templates)
- + ", uids=" + Arrays.toString(uids)
+ + ", networkTemplate=" + template
+ ", thresholdInBytes=" + thresholdInBytes + " ]";
}
@@ -126,23 +99,13 @@
if (obj instanceof DataUsageRequest == false) return false;
DataUsageRequest that = (DataUsageRequest) obj;
return that.requestId == this.requestId
- && Arrays.deepEquals(that.templates, this.templates)
- && Arrays.equals(that.uids, this.uids)
+ && Objects.equals(that.template, this.template)
&& that.thresholdInBytes == this.thresholdInBytes;
}
@Override
public int hashCode() {
- // Start with a non-zero constant.
- int result = 17;
-
- // Include a hash for each field.
- result = 31 * result + requestId;
- result = 31 * result + Arrays.deepHashCode(templates);
- result = 31 * result + Arrays.hashCode(uids);
- result = 31 * result + (int) (thresholdInBytes ^ (thresholdInBytes >>> 32));
-
- return result;
+ return Objects.hash(requestId, template, thresholdInBytes);
}
}
diff --git a/core/java/android/net/INetworkStatsService.aidl b/core/java/android/net/INetworkStatsService.aidl
index 2eea940..e693009 100644
--- a/core/java/android/net/INetworkStatsService.aidl
+++ b/core/java/android/net/INetworkStatsService.aidl
@@ -61,10 +61,10 @@
void advisePersistThreshold(long thresholdBytes);
/** Registers a callback on data usage. */
- DataUsageRequest registerDataUsageCallback(String callingPackage,
+ DataUsageRequest registerUsageCallback(String callingPackage,
in DataUsageRequest request, in Messenger messenger, in IBinder binder);
/** Unregisters a callback on data usage. */
- void unregisterDataUsageRequest(in DataUsageRequest request);
+ void unregisterUsageRequest(in DataUsageRequest request);
}
diff --git a/core/java/android/os/health/PackageHealthStats.java b/core/java/android/os/health/PackageHealthStats.java
index 2c30d5f..fb52cb6 100644
--- a/core/java/android/os/health/PackageHealthStats.java
+++ b/core/java/android/os/health/PackageHealthStats.java
@@ -37,7 +37,7 @@
* Key for a map of the number of times that a package's wakeup alarms have fired
* while the device was on battery.
*
- * @see android.app.AlarmManager.
+ * @see android.app.AlarmManager
*/
@HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENTS)
public static final int MEASUREMENTS_WAKEUP_ALARMS_COUNT = HealthKeys.BASE_PACKAGE + 2;
diff --git a/core/java/android/os/health/SystemHealthManager.java b/core/java/android/os/health/SystemHealthManager.java
index eff5c9a..7c37fa4 100644
--- a/core/java/android/os/health/SystemHealthManager.java
+++ b/core/java/android/os/health/SystemHealthManager.java
@@ -71,7 +71,7 @@
* @return A {@link HealthStats} object containing the metrics for the requested
* application. The keys for this HealthStats object will be from the {@link UidHealthStats}
* class.
- * @see Process#myUid()
+ * @see Process#myUid() Process.myUid()
*/
public HealthStats takeUidSnapshot(int uid) {
try {
diff --git a/core/java/android/os/storage/IMountService.java b/core/java/android/os/storage/IMountService.java
index b9bcd1c..3915b02 100644
--- a/core/java/android/os/storage/IMountService.java
+++ b/core/java/android/os/storage/IMountService.java
@@ -1233,8 +1233,8 @@
}
@Override
- public void addUserKeyAuth(int userId, int serialNumber,
- byte[] token, byte[] secret) throws RemoteException {
+ public void changeUserKey(int userId, int serialNumber,
+ byte[] token, byte[] oldSecret, byte[] newSecret) throws RemoteException {
Parcel _data = Parcel.obtain();
Parcel _reply = Parcel.obtain();
try {
@@ -1242,23 +1242,9 @@
_data.writeInt(userId);
_data.writeInt(serialNumber);
_data.writeByteArray(token);
- _data.writeByteArray(secret);
- mRemote.transact(Stub.TRANSACTION_addUserKeyAuth, _data, _reply, 0);
- _reply.readException();
- } finally {
- _reply.recycle();
- _data.recycle();
- }
- }
-
- @Override
- public void fixateNewestUserKeyAuth(int userId) throws RemoteException {
- Parcel _data = Parcel.obtain();
- Parcel _reply = Parcel.obtain();
- try {
- _data.writeInterfaceToken(DESCRIPTOR);
- _data.writeInt(userId);
- mRemote.transact(Stub.TRANSACTION_fixateNewestUserKeyAuth, _data, _reply, 0);
+ _data.writeByteArray(oldSecret);
+ _data.writeByteArray(newSecret);
+ mRemote.transact(Stub.TRANSACTION_changeUserKey, _data, _reply, 0);
_reply.readException();
} finally {
_reply.recycle();
@@ -1503,9 +1489,7 @@
static final int TRANSACTION_mountAppFuse = IBinder.FIRST_CALL_TRANSACTION + 69;
- static final int TRANSACTION_addUserKeyAuth = IBinder.FIRST_CALL_TRANSACTION + 70;
-
- static final int TRANSACTION_fixateNewestUserKeyAuth = IBinder.FIRST_CALL_TRANSACTION + 71;
+ static final int TRANSACTION_changeUserKey = IBinder.FIRST_CALL_TRANSACTION + 70;
/**
* Cast an IBinder object into an IMountService interface, generating a
@@ -2085,20 +2069,14 @@
reply.writeNoException();
return true;
}
- case TRANSACTION_addUserKeyAuth: {
+ case TRANSACTION_changeUserKey: {
data.enforceInterface(DESCRIPTOR);
int userId = data.readInt();
int serialNumber = data.readInt();
byte[] token = data.createByteArray();
- byte[] secret = data.createByteArray();
- addUserKeyAuth(userId, serialNumber, token, secret);
- reply.writeNoException();
- return true;
- }
- case TRANSACTION_fixateNewestUserKeyAuth: {
- data.enforceInterface(DESCRIPTOR);
- int userId = data.readInt();
- fixateNewestUserKeyAuth(userId);
+ byte[] oldSecret = data.createByteArray();
+ byte[] newSecret = data.createByteArray();
+ changeUserKey(userId, serialNumber, token, oldSecret, newSecret);
reply.writeNoException();
return true;
}
@@ -2474,9 +2452,8 @@
public void createUserKey(int userId, int serialNumber, boolean ephemeral)
throws RemoteException;
public void destroyUserKey(int userId) throws RemoteException;
- public void addUserKeyAuth(int userId, int serialNumber,
- byte[] token, byte[] secret) throws RemoteException;
- public void fixateNewestUserKeyAuth(int userId) throws RemoteException;
+ public void changeUserKey(int userId, int serialNumber,
+ byte[] token, byte[] oldSecret, byte[] newSecret) throws RemoteException;
public void unlockUserKey(int userId, int serialNumber,
byte[] token, byte[] secret) throws RemoteException;
diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java
index 239f2d0..bb131a0 100644
--- a/core/java/android/text/StaticLayout.java
+++ b/core/java/android/text/StaticLayout.java
@@ -754,15 +754,21 @@
&& ellipsize != TextUtils.TruncateAt.MARQUEE));
if (remainingLineCount > 0 && remainingLineCount < breakCount &&
ellipsisMayBeApplied) {
- // Treat the last line and overflowed lines as a single line.
- breaks[remainingLineCount - 1] = breaks[breakCount - 1];
// Calculate width and flag.
float width = 0;
int flag = 0;
for (int i = remainingLineCount - 1; i < breakCount; i++) {
- width += lineWidths[i];
+ if (i == breakCount - 1) {
+ width += lineWidths[i];
+ } else {
+ for (int j = (i == 0 ? 0 : breaks[i - 1]); j < breaks[i]; j++) {
+ width += widths[j];
+ }
+ }
flag |= flags[i] & TAB_MASK;
}
+ // Treat the last line and overflowed lines as a single line.
+ breaks[remainingLineCount - 1] = breaks[breakCount - 1];
lineWidths[remainingLineCount - 1] = width;
flags[remainingLineCount - 1] = flag;
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 8cabf42..130b440 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -125,6 +125,7 @@
private static final boolean DEBUG_CONFIGURATION = false || LOCAL_LOGV;
private static final boolean DEBUG_FPS = false;
private static final boolean DEBUG_INPUT_STAGES = false || LOCAL_LOGV;
+ private static final boolean DEBUG_KEEP_SCREEN_ON = false || LOCAL_LOGV;
/**
* Set to false if we do not want to use the multi threaded renderer. Note that by disabling
@@ -563,9 +564,10 @@
attrs = mWindowAttributes;
setTag();
- if ((mClientWindowLayoutFlags&WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) != 0
+ if (DEBUG_KEEP_SCREEN_ON && (mClientWindowLayoutFlags
+ & WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) != 0
&& (attrs.flags&WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) == 0) {
- Slog.d(mTag, "setView: FLAG_KEEP_SCREEN_ON changed from true to false!!!");
+ Slog.d(mTag, "setView: FLAG_KEEP_SCREEN_ON changed from true to false!");
}
// Keep track of the actual window flags supplied by the client.
mClientWindowLayoutFlags = attrs.flags;
@@ -894,9 +896,11 @@
final int oldInsetBottom = mWindowAttributes.surfaceInsets.bottom;
final int oldSoftInputMode = mWindowAttributes.softInputMode;
final boolean oldHasManualSurfaceInsets = mWindowAttributes.hasManualSurfaceInsets;
- if ((mClientWindowLayoutFlags&WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) != 0
+
+ if (DEBUG_KEEP_SCREEN_ON && (mClientWindowLayoutFlags
+ & WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) != 0
&& (attrs.flags&WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) == 0) {
- Slog.d(mTag, "setLayoutParams: FLAG_KEEP_SCREEN_ON from true to false!!!");
+ Slog.d(mTag, "setLayoutParams: FLAG_KEEP_SCREEN_ON from true to false!");
}
// Keep track of the actual window flags supplied by the client.
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index e68d8a6..c2ff4ef 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -2420,7 +2420,10 @@
android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allows an application to delete packages.
- <p>Not for use by third-party applications. -->
+ <p>Not for use by third-party applications.
+ <p>Starting in {@link android.os.Build.VERSION_CODES#N}, user confirmation is requested
+ when the application deleting the package is not the same application that installed the
+ package. -->
<permission android:name="android.permission.DELETE_PACKAGES"
android:protectionLevel="signature|privileged" />
diff --git a/core/res/res/layout/notification_material_action_list.xml b/core/res/res/layout/notification_material_action_list.xml
index 547d3ca..4670dca 100644
--- a/core/res/res/layout/notification_material_action_list.xml
+++ b/core/res/res/layout/notification_material_action_list.xml
@@ -21,7 +21,7 @@
<com.android.internal.widget.NotificationActionListLayout
android:id="@+id/actions"
android:layout_width="match_parent"
- android:layout_height="56dp"
+ android:layout_height="@dimen/notification_action_list_height"
android:paddingEnd="4dp"
android:orientation="horizontal"
android:gravity="center_vertical"
diff --git a/core/res/res/values-be-rBY/strings.xml b/core/res/res/values-be-rBY/strings.xml
index 7fa9f16..2ef61e8 100644
--- a/core/res/res/values-be-rBY/strings.xml
+++ b/core/res/res/values-be-rBY/strings.xml
@@ -269,7 +269,7 @@
<string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"Атрымайце змесцiва акна"</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"Вывучыце змесцiва акна, з якiм вы працуеце."</string>
<string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"Уключыце Explore by Touch"</string>
- <string name="capability_desc_canRequestTouchExploration" msgid="7543249041581408313">"Элементы, да якiх дакранулiся, будуць агучаны, а з экранам можна будзе ўзаемадзейнічаць пры дапамозе жэстаў."</string>
+ <string name="capability_desc_canRequestTouchExploration" msgid="7543249041581408313">"Элементы, да якіх дакрануліся, будуць агучаны, а экранам можна даследаваць пры дапамозе жэстаў."</string>
<string name="capability_title_canRequestEnhancedWebAccessibility" msgid="1739881766522594073">"Уключыце паляпшэнне вэб-даступнасці"</string>
<string name="capability_desc_canRequestEnhancedWebAccessibility" msgid="7881063961507511765">"Сцэнарыi могуць быць усталяваны, каб зрабіць змесцiва прыкладання больш даступным."</string>
<string name="capability_title_canRequestFilterKeyEvents" msgid="2103440391902412174">"Глядзiце, што набiраеце"</string>
@@ -1136,7 +1136,7 @@
<string name="usb_ptp_notification_title" msgid="1347328437083192112">"USB для перадачы фота"</string>
<string name="usb_midi_notification_title" msgid="4850904915889144654">"USB для MIDI"</string>
<string name="usb_accessory_notification_title" msgid="7848236974087653666">"Падключаны да USB-прылады"</string>
- <string name="usb_notification_message" msgid="3370903770828407960">"Дакраніцеся, каб атрымаць больш параметраў."</string>
+ <string name="usb_notification_message" msgid="3370903770828407960">"Дакраніцеся, каб атрымаць іншыя параметры."</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"Прылада адладкі USB падключана"</string>
<string name="adb_active_notification_message" msgid="4948470599328424059">"Дакраніцеся, каб адключыць адладку USB."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Стварэнне справаздачы пра памылку…"</string>
@@ -1232,13 +1232,13 @@
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Падключэнне заўсёды ўключанага VPN..."</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"Заўсёды ўключаны i падключаны VPN"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"Памылка заўсёды ўключанага VPN"</string>
- <string name="vpn_lockdown_config" msgid="4655589351146766608">"Дакраніцеся, каб змяніць канфігурацыю"</string>
+ <string name="vpn_lockdown_config" msgid="4655589351146766608">"Дакраніцеся, каб сканфігураваць"</string>
<string name="upload_file" msgid="2897957172366730416">"Выберыце файл"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"Файл не выбраны"</string>
<string name="reset" msgid="2448168080964209908">"Скінуць"</string>
<string name="submit" msgid="1602335572089911941">"Перадаць"</string>
<string name="car_mode_disable_notification_title" msgid="3164768212003864316">"Рэжым \"У машыне\" ўключаны"</string>
- <string name="car_mode_disable_notification_message" msgid="6301524980144350051">"Дакраніцеся, каб выйсці з рэжыму \"Ў аўтамабілі\"."</string>
+ <string name="car_mode_disable_notification_message" msgid="6301524980144350051">"Дакраніцеся, каб выйсці з рэжыму \"У машыне\"."</string>
<string name="tethered_notification_title" msgid="3146694234398202601">"USB-мадэм або кропка доступу Wi-Fi актыўныя"</string>
<string name="tethered_notification_message" msgid="2113628520792055377">"Дакраніцеся, каб наладзіць."</string>
<string name="back_button_label" msgid="2300470004503343439">"Назад"</string>
@@ -1275,7 +1275,7 @@
<string name="add_account_button_label" msgid="3611982894853435874">"Дадаць уліковы запіс"</string>
<string name="number_picker_increment_button" msgid="2412072272832284313">"Павялічыць"</string>
<string name="number_picker_decrement_button" msgid="476050778386779067">"Паменшыць"</string>
- <string name="number_picker_increment_scroll_mode" msgid="5259126567490114216">"Націсніце і ўтрымлівайце <xliff:g id="VALUE">%s</xliff:g>."</string>
+ <string name="number_picker_increment_scroll_mode" msgid="5259126567490114216">"<xliff:g id="VALUE">%s</xliff:g> – Націсніце і ўтрымлівайце."</string>
<string name="number_picker_increment_scroll_action" msgid="9101473045891835490">"Правядзіце пальцам уверх, каб павялічыць, або ўніз, каб паменшыць."</string>
<string name="time_picker_increment_minute_button" msgid="8865885114028614321">"Павялічыць лічбу хвілін."</string>
<string name="time_picker_decrement_minute_button" msgid="6246834937080684791">"Паменшыць лічбу хвілін."</string>
@@ -1319,7 +1319,7 @@
<string name="storage_usb" msgid="3017954059538517278">"USB-назапашвальнік"</string>
<string name="extract_edit_menu_button" msgid="8940478730496610137">"Рэдагаваць"</string>
<string name="data_usage_warning_title" msgid="1955638862122232342">"Папярэджанне выкарыстання дадзеных"</string>
- <string name="data_usage_warning_body" msgid="6660692274311972007">"Кран. для прагл. выкар. і налад."</string>
+ <string name="data_usage_warning_body" msgid="6660692274311972007">"Прагляд выкарыстання і налад."</string>
<string name="data_usage_3g_limit_title" msgid="4361523876818447683">"Дасягнуты ліміт трафіку 2G-3G"</string>
<string name="data_usage_4g_limit_title" msgid="4609566827219442376">"Дасягнуты ліміт трафіку 4G"</string>
<string name="data_usage_mobile_limit_title" msgid="557158376602636112">"Дасягн. ліміт маб.перадачы даных"</string>
@@ -1549,8 +1549,8 @@
<string name="select_year" msgid="7952052866994196170">"Выберыце год"</string>
<string name="deleted_key" msgid="7659477886625566590">"Выдалена: <xliff:g id="KEY">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> (праца)"</string>
- <string name="lock_to_app_toast" msgid="1420543809500606964">"Каб адмацаваць гэты экран, краніце і ўтрымлівайце кнопку \"Назад\"."</string>
- <string name="lock_to_app_toast_accessible" msgid="2302154926850846096">"Каб адмацаваць гэты экран, краніце і ўтрымлівайце кнопку \"Агляд\"."</string>
+ <string name="lock_to_app_toast" msgid="1420543809500606964">"Каб адмацаваць гэты экран, дакраніцеся і ўтрымлівайце кнопку \"Назад\"."</string>
+ <string name="lock_to_app_toast_accessible" msgid="2302154926850846096">"Каб адмацаваць гэты экран, дакраніцеся і ўтрымлівайце кнопку \"Агляд\"."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Праграма замацавана: адмацаванне на гэтай прыладзе не дапускаецца."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Экран замацаваны"</string>
<string name="lock_to_app_exit" msgid="8598219838213787430">"Экран адмацаваны"</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 858cf27..7590ea9 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -263,7 +263,7 @@
<string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"Recuperar el contenido de la ventana"</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"Inspecciona el contenido de una ventana con la que estés interactuando."</string>
<string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"Activar la exploración táctil"</string>
- <string name="capability_desc_canRequestTouchExploration" msgid="7543249041581408313">"Los elementos seleccionados se dicen en voz alta y se puede explorar la pantalla mediante gestos."</string>
+ <string name="capability_desc_canRequestTouchExploration" msgid="7543249041581408313">"Los elementos que tocas se dicen en voz alta y se puede explorar la pantalla mediante gestos."</string>
<string name="capability_title_canRequestEnhancedWebAccessibility" msgid="1739881766522594073">"Activar la accesibilidad web mejorada"</string>
<string name="capability_desc_canRequestEnhancedWebAccessibility" msgid="7881063961507511765">"Es posible que se instalen secuencias de comandos para que el contenido de las aplicaciones sea más accesible."</string>
<string name="capability_title_canRequestFilterKeyEvents" msgid="2103440391902412174">"Observar el texto que escribes"</string>
@@ -662,7 +662,7 @@
<string name="keyguard_password_enter_puk_code" msgid="4800725266925845333">"Introduce el código PUK y un nuevo código PIN."</string>
<string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"Código PUK"</string>
<string name="keyguard_password_enter_pin_prompt" msgid="8027680321614196258">"Nuevo código PIN"</string>
- <string name="keyguard_password_entry_touch_hint" msgid="2644215452200037944"><font size="17">"Toca para insertar contraseña"</font></string>
+ <string name="keyguard_password_entry_touch_hint" msgid="2644215452200037944"><font size="17">"Toca para escribir contraseña"</font></string>
<string name="keyguard_password_enter_password_code" msgid="1054721668279049780">"Introduce la contraseña para desbloquear."</string>
<string name="keyguard_password_enter_pin_password_code" msgid="6391755146112503443">"Introduce el código PIN para desbloquear."</string>
<string name="keyguard_password_wrong_pin_code" msgid="2422225591006134936">"Código PIN incorrecto"</string>
@@ -1124,7 +1124,7 @@
<string name="ext_media_new_notification_message" msgid="7589986898808506239">"Nueva <xliff:g id="NAME">%s</xliff:g> detectada"</string>
<string name="ext_media_ready_notification_message" msgid="4083398150380114462">"Para transferir fotos y multimedia"</string>
<string name="ext_media_unmountable_notification_title" msgid="8295123366236989588">"Medio externo (<xliff:g id="NAME">%s</xliff:g>) dañado"</string>
- <string name="ext_media_unmountable_notification_message" msgid="2343202057122495773">"<xliff:g id="NAME">%s</xliff:g> está dañado. Toca para solucionar el problema."</string>
+ <string name="ext_media_unmountable_notification_message" msgid="2343202057122495773">"<xliff:g id="NAME">%s</xliff:g> está en mal estado. Toca para solucionar el problema."</string>
<string name="ext_media_unsupported_notification_title" msgid="3797642322958803257">"Medio externo (<xliff:g id="NAME">%s</xliff:g>) no admitido"</string>
<string name="ext_media_unsupported_notification_message" msgid="6121601473787888589">"El dispositivo no admite este medio externo (<xliff:g id="NAME">%s</xliff:g>). Toca para configurarlo con un formato admitido."</string>
<string name="ext_media_badremoval_notification_title" msgid="3206248947375505416">"Extracción inesperada de <xliff:g id="NAME">%s</xliff:g>"</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index c32b98c..27aecad 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -310,7 +310,7 @@
<string name="permdesc_enableCarMode" msgid="4853187425751419467">"به برنامه اجازه میدهد تا حالت خودرو را فعال کند."</string>
<string name="permlab_killBackgroundProcesses" msgid="3914026687420177202">"بستن سایر برنامهها"</string>
<string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"به برنامه امکان میدهد به فرآیندهای پسزمینه سایر برنامهها پایان دهد. این ممکن است باعث شود سایر برنامهها متوقف شوند."</string>
- <string name="permlab_systemAlertWindow" msgid="3543347980839518613">"ترسیم روی برنامههای دیگر"</string>
+ <string name="permlab_systemAlertWindow" msgid="3543347980839518613">"نمایش روی برنامههای دیگر"</string>
<string name="permdesc_systemAlertWindow" msgid="8584678381972820118">"به برنامه اجازه میدهد که در بالا یا بخشهایی از رابط کاربری دیگر برنامههای کاربردی متصل شود. این کار میتواند در استفاده شما از رابط هر برنامه کاربردی تداخل ایجاد کند یا آنچه را که به نظر خود در دیگر برنامههای کاربردی میبینید، تغییر دهد."</string>
<string name="permlab_persistentActivity" msgid="8841113627955563938">"همیشه برنامه اجرا شود"</string>
<string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"به برنامه امکان میدهد قسمتهایی از خود را در حافظه دائمی کند. این کار حافظه موجود را برای سایر برنامهها محدود کرده و باعث کندی رایانهٔ لوحی میشود."</string>
diff --git a/core/res/res/values-gl-rES/strings.xml b/core/res/res/values-gl-rES/strings.xml
index 455632d..cf04177 100644
--- a/core/res/res/values-gl-rES/strings.xml
+++ b/core/res/res/values-gl-rES/strings.xml
@@ -310,7 +310,7 @@
<string name="permdesc_enableCarMode" msgid="4853187425751419467">"Permite á aplicación activar o modo coche."</string>
<string name="permlab_killBackgroundProcesses" msgid="3914026687420177202">"pechar outras aplicacións"</string>
<string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"Permite á aplicación finalizar procesos en segundo plano doutras aplicacións. É posible que esta acción provoque que outras aplicacións deixen de funcionar."</string>
- <string name="permlab_systemAlertWindow" msgid="3543347980839518613">"debuxar sobre outras aplicacións"</string>
+ <string name="permlab_systemAlertWindow" msgid="3543347980839518613">"superpoñerse a outras aplicacións"</string>
<string name="permdesc_systemAlertWindow" msgid="8584678381972820118">"Permite á aplicación debuxar sobre outras aplicacións ou partes da interface de usuario. É posible que interfiran co teu uso da interface de calquera aplicación ou que cambien o que cres que estás vendo noutras aplicacións."</string>
<string name="permlab_persistentActivity" msgid="8841113627955563938">"facer que a aplicación se execute sempre"</string>
<string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"Permite á aplicación converter partes súas como persistentes na memoria. Esta acción pode limitar a cantidade memoria dispoñible para outras aplicacións e reducir a velocidade de funcionamento do tablet."</string>
diff --git a/core/res/res/values-hy-rAM/strings.xml b/core/res/res/values-hy-rAM/strings.xml
index 260992a..33c8f7c 100644
--- a/core/res/res/values-hy-rAM/strings.xml
+++ b/core/res/res/values-hy-rAM/strings.xml
@@ -263,7 +263,7 @@
<string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"Առբերել պատուհանի բովանդակությունը"</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"Ստուգեք պատուհանի բովանդակությունը, որի հետ փոխգործակցում եք:"</string>
<string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"Միացնել Հպման միջոցով հետազոտումը"</string>
- <string name="capability_desc_canRequestTouchExploration" msgid="7543249041581408313">"Տարրերը, որոնց հպեք, բարձրաձայն կարտասանվեն, և էկրանը հնարավոր կլինի ուսումնասիրել ժեստերով:"</string>
+ <string name="capability_desc_canRequestTouchExploration" msgid="7543249041581408313">"Ուսումնաիրեք էկրանը այն շոշափելով։ Այս կամ այն տարրին հպելուց հետո դրանք բարձրաձայն կնկարագրվեն։"</string>
<string name="capability_title_canRequestEnhancedWebAccessibility" msgid="1739881766522594073">"Միացնել ընդլայնված վեբ մատչելիությունը"</string>
<string name="capability_desc_canRequestEnhancedWebAccessibility" msgid="7881063961507511765">"Հնարավոր է սկրիպտներ տեղադրվեն` ծրագրի բովանդակությունն ավելի մատչելի դարձնելու համար:"</string>
<string name="capability_title_canRequestFilterKeyEvents" msgid="2103440391902412174">"Զննել ձեր մուտքագրած տեքստը"</string>
@@ -1124,7 +1124,7 @@
<string name="ext_media_new_notification_message" msgid="7589986898808506239">"Հայտնաբերվել է նոր <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_ready_notification_message" msgid="4083398150380114462">"Լուսանկարներ և մեդիա ֆայլեր տեղափոխելու համար"</string>
<string name="ext_media_unmountable_notification_title" msgid="8295123366236989588">"<xliff:g id="NAME">%s</xliff:g>-ը վնասված է"</string>
- <string name="ext_media_unmountable_notification_message" msgid="2343202057122495773">"<xliff:g id="NAME">%s</xliff:g> անունը վնասված է: Հպեք՝ շտկելու համար:"</string>
+ <string name="ext_media_unmountable_notification_message" msgid="2343202057122495773">"<xliff:g id="NAME">%s</xliff:g>-ը վնասված է: Հպեք՝ շտկելու համար:"</string>
<string name="ext_media_unsupported_notification_title" msgid="3797642322958803257">"Չապահովվող <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unsupported_notification_message" msgid="6121601473787888589">"Այս սարքը չի աջակցում այս <xliff:g id="NAME">%s</xliff:g>-ը: Հպեք՝ աջակցվող ձևաչափով կարգավորելու համար:"</string>
<string name="ext_media_badremoval_notification_title" msgid="3206248947375505416">"<xliff:g id="NAME">%s</xliff:g>-ը հեռացվել է առանց անջատելու"</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 316626d..29e6dec5 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -269,7 +269,7 @@
<string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"אחזור תוכן של חלון"</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"בדוק את התוכן של חלון שאיתו אתה מבצע אינטראקציה."</string>
<string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"הפעלה של \'גילוי באמצעות מגע\'"</string>
- <string name="capability_desc_canRequestTouchExploration" msgid="7543249041581408313">"פריטים שעליהם תקיש ייאמרו בקול, ותוכל לנווט במסך באמצעות תנועות."</string>
+ <string name="capability_desc_canRequestTouchExploration" msgid="7543249041581408313">"פריטים שעליהם תקיש יוקראו בקול, ותוכל לנווט במסך באמצעות תנועות."</string>
<string name="capability_title_canRequestEnhancedWebAccessibility" msgid="1739881766522594073">"הפעלה של גישה משופרת לאינטרנט"</string>
<string name="capability_desc_canRequestEnhancedWebAccessibility" msgid="7881063961507511765">"ייתכן שסקריפטים יותקנו על מנת להקל את הגישה אל תוכן של אפליקציות."</string>
<string name="capability_title_canRequestFilterKeyEvents" msgid="2103440391902412174">"הצגת טקסט בזמן הקלדה"</string>
diff --git a/core/res/res/values-kk-rKZ/strings.xml b/core/res/res/values-kk-rKZ/strings.xml
index 60671ab..984035d 100644
--- a/core/res/res/values-kk-rKZ/strings.xml
+++ b/core/res/res/values-kk-rKZ/strings.xml
@@ -1286,7 +1286,7 @@
<string name="storage_usb" msgid="3017954059538517278">"USB жады"</string>
<string name="extract_edit_menu_button" msgid="8940478730496610137">"Өзгерту"</string>
<string name="data_usage_warning_title" msgid="1955638862122232342">"Дерекқор қолдануға қатысты ескерту"</string>
- <string name="data_usage_warning_body" msgid="6660692274311972007">"Қолданыс пен параметрлерді көру үшін түртіңіз."</string>
+ <string name="data_usage_warning_body" msgid="6660692274311972007">"Трафик пен параметрлерді көру үшін түртіңіз."</string>
<string name="data_usage_3g_limit_title" msgid="4361523876818447683">"2G-3G деректер шегіне жеттіңіз"</string>
<string name="data_usage_4g_limit_title" msgid="4609566827219442376">"4G деректер шегіне жеттіңіз"</string>
<string name="data_usage_mobile_limit_title" msgid="557158376602636112">"Ұялы деректер шегіне жеттіңіз"</string>
diff --git a/core/res/res/values-sq-rAL/strings.xml b/core/res/res/values-sq-rAL/strings.xml
index 51015f2..52ddeb0 100644
--- a/core/res/res/values-sq-rAL/strings.xml
+++ b/core/res/res/values-sq-rAL/strings.xml
@@ -1242,7 +1242,7 @@
<string name="add_account_button_label" msgid="3611982894853435874">"Shto llogari"</string>
<string name="number_picker_increment_button" msgid="2412072272832284313">"Rrit"</string>
<string name="number_picker_decrement_button" msgid="476050778386779067">"Pakëso"</string>
- <string name="number_picker_increment_scroll_mode" msgid="5259126567490114216">"Prek dhe mbaj të shtypur te <xliff:g id="VALUE">%s</xliff:g>."</string>
+ <string name="number_picker_increment_scroll_mode" msgid="5259126567490114216">"Prek dhe mbaj të shtypur <xliff:g id="VALUE">%s</xliff:g>."</string>
<string name="number_picker_increment_scroll_action" msgid="9101473045891835490">"Rrëshqit lart për të rritur dhe poshtë për të pakësuar."</string>
<string name="time_picker_increment_minute_button" msgid="8865885114028614321">"Rrit vlerat për minutë"</string>
<string name="time_picker_decrement_minute_button" msgid="6246834937080684791">"Pakëso vlerat për minutë"</string>
@@ -1514,8 +1514,8 @@
<string name="select_year" msgid="7952052866994196170">"Përzgjidh vitin"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> u fshi"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Puna <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <string name="lock_to_app_toast" msgid="1420543809500606964">"Për të hequr gozhdimin e ekranit, prek dhe mbaj të shtypur te \"Prapa\"."</string>
- <string name="lock_to_app_toast_accessible" msgid="2302154926850846096">"Për të hequr gozhdimin e ekranit, prek dhe mbaj të shtypur te \"Përmbledhja\"."</string>
+ <string name="lock_to_app_toast" msgid="1420543809500606964">"Për të hequr gozhdimin e ekranit, prek dhe mbaj të shtypur \"Prapa\"."</string>
+ <string name="lock_to_app_toast_accessible" msgid="2302154926850846096">"Për të hequr gozhdimin e ekranit, prek dhe mbaj të shtypur \"Përmbledhja\"."</string>
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Ekrani është i gozhduar. Anulimi i mbërthimit nuk lejohet nga organizata jote."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Ekrani u gozhdua"</string>
<string name="lock_to_app_exit" msgid="8598219838213787430">"Ekrani u hoq nga gozhdimi"</string>
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index 8ce922e..3ba6ce1 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -152,6 +152,9 @@
<!-- The margin on the end of the content view with a picture.-->
<dimen name="notification_content_picture_margin">56dp</dimen>
+ <!-- The height of the notification action list -->
+ <dimen name="notification_action_list_height">56dp</dimen>
+
<!-- height of the content margin to accomodate for the header -->
<dimen name="notification_content_margin_top">37.5dp</dimen>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index c64a934..29818df 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2584,6 +2584,8 @@
<java-symbol type="dimen" name="input_extract_action_button_width" />
<java-symbol type="dimen" name="input_extract_action_button_height" />
+ <java-symbol type="dimen" name="notification_action_list_height" />
+
<!-- TV Remote Service package -->
<java-symbol type="string" name="config_tvRemoteServicePackage" />
diff --git a/docs/html/_redirects.yaml b/docs/html/_redirects.yaml
index f0986aa..d13a635 100644
--- a/docs/html/_redirects.yaml
+++ b/docs/html/_redirects.yaml
@@ -988,7 +988,7 @@
- from: /tools/help/theme-editor.html
to: /studio/write/theme-editor.html
- from: /tools/help/traceview.html
- to: /studio/profile/traceview-commandline.html
+ to: /studio/profile/traceview.html
- from: /tools/help/translations-editor.html
to: /studio/write/translations-editor.html
- from: /tools/help/uiautomator/Configurator.html
@@ -1113,6 +1113,26 @@
to: /studio/test/index.html
- from: /tools/testing/testing-tools.html
to: /studio/test/index.html
+- from: /tools/performance/importing-legacy-apps.html
+ to: /studio/projects/index.html
+- from: /tools/performance/comparison.html
+ to: /studio/profile/android-monitor.html
+- from: /tools/performance/memory-monitor/index.html
+ to: /studio/profile/am-memory.html
+- from: /tools/devices/index.html
+ to: /studio/run/managing-avds.html
+- from: /tools/extras/index.html
+ to: /studio/intro/update.html
+- from: /tools/workflow.html
+ to: /studio/guide/workflow.html
+- from: /installing/studio-androidview.html
+ to: /studio/projects/index.html
+- from: /installing/studio-tips.html
+ to: /studio/intro/index.html
+- from: /tools/help/ddms.html
+ to: /studio/profile/ddms.html
+- from: /tools/revisions/index.html
+ to: /studio/releases/index.html
# Just incase something was missed, go to intro page
diff --git a/docs/html/jd_collections.js b/docs/html/jd_collections.js
index f155521..7ed40c0 100644
--- a/docs/html/jd_collections.js
+++ b/docs/html/jd_collections.js
@@ -169,6 +169,22 @@
"preview/features/tv-recording-api.html"
]
},
+ "wear/preview/landing": {
+ "title": "",
+ "resources": [
+ "preview/api-overview.html",
+ "preview/download.html",
+ "preview/setup-sdk.html"
+ ]
+ },
+ "wear/preview/landing/resources": {
+ "title": "",
+ "resources": [
+ "design/wear/index.html",
+ "training/building-wearables.html",
+ "training/wearables/ui/index.html"
+ ]
+ },
"google/landing/services": {
"title": "",
"resources": [
diff --git a/docs/html/jd_extras_en.js b/docs/html/jd_extras_en.js
index 18e1f99..9c75c7c 100644
--- a/docs/html/jd_extras_en.js
+++ b/docs/html/jd_extras_en.js
@@ -28,6 +28,233 @@
/* TODO Remove standard resources from here, such as below
*/
{
+ "title":"Meet Android Studio",
+ "summary":"The basics of working with Android Studio, from projects to build and performance.",
+ "url":"studio/intro/index.html",
+ "image":"studio/images/intro/main-window_2-1_2x.png",
+ "type":"studio",
+ "keywords": ["studio","sdk","tools","firstapp"],
+ "tags": ["studio","sdk","tools","firstapp"],
+ "lang":"en"
+ },
+ {
+ "title":"Configure Your Build",
+ "summary":"Learn about Android Studio's build configuration.",
+ "url":"studio/build/index.html",
+ "image":"images/tools/studio/build-process_2x.png",
+ "type":"studio",
+ "keywords": ["studio","configuration"],
+ "tags": ["studio","configuration"],
+ "lang":"en"
+ },
+ {
+ "title":"Android Studio Features",
+ "summary":"A quick look at key Android Studio features.",
+ "url":"studio/features.html",
+ "image":"images/cards/card-studio-modules_crop_2x.png",
+ "type":"studio",
+ "keywords": ["studio","tools","sdk"],
+ "tags": ["studio"],
+ "lang":"en"
+ },
+ {
+ "title":"Using Code Templates",
+ "summary":"Quickly create Android app projects with various UI or functional components.",
+ "url":"studio/projects/templates.html",
+ "image":"images/cards/card-using-code-templates_16x9_2x.png",
+ "type":"studio",
+ "keywords": ["studio","templates","firstapp"],
+ "tags": ["studio","templates","firstapp"],
+ "lang":"en"
+ },
+ {
+ "title":"Publishing Overview",
+ "summary":"Start here for an overview of publishing options for Android apps.",
+ "url":"studio/publish/index.html",
+ "image":"images/publishing/publishing_overview.png",
+ "type":"studio",
+ "keywords": [],
+ "tags": [],
+ "lang":"en"
+ },
+ {
+ "title":"Preparing for Release",
+ "summary":"Developer documentation on how to build the signed, release-ready APK. This process is the same for all Android apps.",
+ "url":"studio/publish/preparing.html",
+ "image":"images/publishing/publishing_overview_prep.png",
+ "type":"studio",
+ "keywords": [],
+ "tags": [],
+ "lang":"en"
+ },
+ {
+ "title":"Network Monitor",
+ "summary":"The Network Monitor makes it possible to track when your application is making network requests. Using this tool, you can monitor how and when your app transfers data, and optimize the underlying code appropriately. By monitoring the frequency of data\u2026",
+ "url":"studio/profile/am-network.html",
+ "image":"images/tools/thumbnails/am-networkmon.png",
+ "type":"studio",
+ "keywords": ["monitor"],
+ "tags": ["monitor"],
+ "lang":"en"
+ },
+ {
+ "title":"Memory Monitor",
+ "summary":"Android Studio provides a Memory Monitor so you can more easily monitor app performance and memory usage to find deallocated objects, locate memory leaks, and track the amount of memory the connected device is using. The Memory Monitor reports how your\u2026",
+ "url":"studio/profile/am-memory.html",
+ "image":"images/tools/thumbnails/am-memorymon.png",
+ "type":"studio",
+ "keywords": ["monitor"],
+ "tags": ["monitor"],
+ "lang":"en"
+ },
+ {
+ "title":"UI/Application Exerciser Monkey",
+ "summary":"The Monkey is a program that runs on your emulator or device and generates pseudo-random streams of user events such as clicks, touches, or gestures, as well as a number of system-level events. You can use the Monkey to stress-test applications that you\u2026",
+ "url":"studio/test/monkey.html",
+ "type":"studio",
+ "keywords": [],
+ "tags": [],
+ "lang":"en"
+ },
+ {
+ "title":"CPU Monitor",
+ "summary":"The CPU Monitor lets you easily monitor the central processing unit (CPU) usage of your app. It displays CPU usage in real time and displays the percentage of total CPU time (including all cores) used by user and kernel mode. In user mode, the code must\u2026",
+ "url":"studio/profile/am-cpu.html",
+ "image":"images/tools/thumbnails/am-cpumon.png",
+ "type":"studio",
+ "keywords": ["monitor"],
+ "tags": ["monitor"],
+ "lang":"en"
+ },
+ {
+ "title":"Shrink Your Code and Resources",
+ "summary":"Make your APK file smaller and more secure by shrinking your code and resources.",
+ "url":"studio/build/shrink-code.html",
+ "type":"studio",
+ "keywords": [],
+ "tags": [],
+ "lang":"en"
+ },
+ {
+ "title":"logcat Monitor",
+ "summary":"The Android logging system provides a mechanism for collecting and viewing system debug output. logcat Monitor displays messages that you added to your app by using the Log class, as well as system messages, such as stack traces when the emulator throws\u2026",
+ "url":"studio/debug/am-logcat.html",
+ "image":"images/tools/thumbnails/am-logcatmon.png",
+ "type":"studio",
+ "keywords": ["monitor"],
+ "tags": ["monitor"],
+ "lang":"en"
+ },
+ {
+ "title":"GPU Monitor",
+ "summary":"The GPU Monitor gives you a quick visual representation of how much time it takes to render the frames of a UI window. It profiles the amount of time it takes for the render thread to prepare, process, and execute the draw commands. The GPU Monitor can\u2026",
+ "url":"studio/profile/am-gpu.html",
+ "image":"images/tools/thumbnails/am-gpumon.png",
+ "type":"studio",
+ "keywords": ["monitor"],
+ "tags": ["monitor"],
+ "lang":"en"
+ },
+ {
+ "title":"HPROF Viewer and Analyzer",
+ "summary":"Use the Memory Monitor to dump the Java heap to an HPROF file. The HPROF Viewer displays classes, instances of each class, and a reference tree to help you track memory usage and find memory leaks.",
+ "url":"studio/profile/am-hprof.html",
+ "image":"images/tools/thumbnails/am_hprofviewer.png",
+ "type":"tools",
+ "keywords": ["android","performance","profiling","tools","monitor"],
+ "tags": ["android","performance","profiling","tools","monitor"],
+ "lang":"en"
+ },
+ {
+ "title":"Video Capture",
+ "summary":"Use the Video tool to make a video of the display on a hardware device.",
+ "url":"studio/debug/am-video.html",
+ "image":"images/tools/thumbnails/am_video.png",
+ "type":"tools",
+ "keywords": ["android","performance","profiling","tools","monitor"],
+ "tags": ["android","performance","profiling","tools","monitor"],
+ "lang":"en"
+ },
+ {
+ "title":"Screen Capture",
+ "summary":"Use the Screen Capture tool to take a screenshot of the display on a hardware device or the emulator. Optionally display the screenshot within a graphic of a device.",
+ "url":"studio/debug/am-screenshot.html",
+ "image":"images/tools/thumbnails/am_screenshot.png",
+ "type":"tools",
+ "keywords": ["android","performance","profiling","tools","monitor"],
+ "tags": ["android","performance","profiling","tools","monitor"],
+ "lang":"en"
+ },
+ {
+ "title":"Allocation Tracker",
+ "summary":"Use the Memory Monitor to capture allocation data about your app. The Allocation Tracker displays each method responsible for an allocation, as well as the allocation size and number of instances.",
+ "url":"studio/profile/am-allocation.html",
+ "image":"images/tools/thumbnails/am_alloctracker.png",
+ "type":"tools",
+ "keywords": ["android","performance","profiling","tools","monitor"],
+ "tags": ["android","performance","profiling","tools","monitor"],
+ "lang":"en"
+ },
+ {
+ "title":"Method Trace",
+ "summary":"Use the CPU Monitor to perform a method trace on your app. View call stack and timing information in the method trace display.",
+ "url":"studio/profile/am-methodtrace.html",
+ "image":"images/tools/thumbnails/am_methodtrace.png",
+ "type":"tools",
+ "keywords": ["android","performance","profiling","tools","monitor"],
+ "tags": ["android","performance","profiling","tools","monitor"],
+ "lang":"en"
+ },
+ {
+ "title":"System Information",
+ "summary":"Use the System Information tool to capture <code>dumpsys</code> information about your app. View activity manager, package, memory usage, and graphics state information.",
+ "url":"studio/profile/am-sysinfo.html",
+ "image":"images/tools/thumbnails/am_sysinfo.png",
+ "type":"tools",
+ "keywords": ["android","performance","profiling","tools","monitor"],
+ "tags": ["android","performance","profiling","tools","monitor"],
+ "lang":"en"
+ },
+ {
+ "title":"monkeyrunner",
+ "summary":"The monkeyrunner tool provides an API for writing programs that control an Android device or emulator from outside of Android code. With monkeyrunner, you can write a Python program that installs an Android application or test package, runs it, sends \u2026",
+ "url":"studio/test/monkeyrunner/index.html",
+ "type":"studio",
+ "keywords": [],
+ "tags": [],
+ "lang":"en"
+ },
+ {
+ "title":"Testing from the Command-Line",
+ "summary":"This document describes how to create and run tests directly from the command line. This document assumes that you already know how to create a Android application in your programming environment. You can run tests from the command-line, either with Gradle\u2026",
+ "url":"studio/test/command-line.html",
+ "type":"studio",
+ "keywords": [],
+ "tags": [],
+ "lang":"en"
+ },
+ {
+ "title":"Test Your App",
+ "summary":"This document describes key concepts related to Android app testing. It assumes you have a basic knowledge of the JUnit testing framework. Android testing is based on JUnit. In general, a JUnit test is a method whose statements test a part of the application\u2026",
+ "url":"studio/test/index.html",
+ "image":"images/testing/test_framework.png",
+ "type":"studio",
+ "keywords": [],
+ "tags": [],
+ "lang":"en"
+ },
+ {
+ "title":"Android Studio 2.0",
+ "category":"",
+ "summary":"Android Studio 2.0 is the fastest way to build high quality, performant apps for the Android platform, including phones and tablets, Android Auto, Android Wear, and Android TV. As the official IDE from Google, Android Studio includes everything you…",
+ "url":"http://android-developers.blogspot.com/2016/04/android-studio-2-0.html",
+ "group":"",
+ "keywords": [],
+ "tags": ['studio'],
+ "image":"https://1.bp.blogspot.com/-vxXg6Inv_WA/VwaJ0uzSf_I/AAAAAAAACr4/xzszbcRzWRgSaHXpOpYroG7u6bgsFJjqw/s200/image03.png",
+ "type":"blog"
+ },
+ {
"title":"Writing More Code by Writing Less Code with Android Studio Live Templates",
"category":"",
"summary":"Unless you’re getting paid by the keystroke, no one wants to write repetitive boilerplate code.",
@@ -3413,9 +3640,9 @@
"develop/landing/mainlinks": {
"title": "",
"resources": [
- "tools/studio/index.html",
+ "studio/index.html",
"samples/new/index.html",
- "tools/projects/templates.html"
+ "studio/projects/templates.html"
]
},
"develop/landing/latest": {
@@ -4368,8 +4595,8 @@
"distribute/toolsreference/launchchecklist/understanding": {
"title": "",
"resources": [
- "tools/publishing/publishing_overview.html",
- "tools/publishing/preparing.html"
+ "studio/publish/index.html",
+ "studio/publish/preparing.html"
]
},
"distribute/toolsreference/launchchecklist/policies": {
@@ -4404,7 +4631,7 @@
"title": "",
"resources": [
"google/play/expansion-files.html",
- "tools/help/proguard.html"
+ "studio/build/shrink-code.html"
]
},
"distribute/toolsreference/launchchecklist/platform": {
@@ -4567,6 +4794,22 @@
"training/wearables/ui/index.html"
]
},
+ "wear/preview/landing": {
+ "title": "",
+ "resources": [
+ "preview/api-overview.html",
+ "preview/download.html",
+ "preview/setup-sdk.html"
+ ]
+ },
+ "wear/preview/landing/resources": {
+ "title": "",
+ "resources": [
+ "design/wear/index.html",
+ "training/building-wearables.html",
+ "training/wearables/ui/index.html"
+ ]
+ },
"design/auto/auto_ui_guidelines": {
"title": "",
"resources": [
@@ -4625,17 +4868,17 @@
"title": "",
"resources": [
"training/testing/start/index.html",
- "tools/testing/testing_android.html",
+ "studio/test/index.html",
"https://www.youtube.com/watch?v=vdasFFfXKOY"
]
},
"training/testing/tools": {
"title": "",
"resources": [
- "tools/testing-support-library/index.html",
- "tools/help/monkey.html",
- "tools/help/monkeyrunner_concepts.html",
- "tools/testing/testing_otheride.html",
+ "topic/libraries/testing-support-library/index.html",
+ "studio/test/monkey.html",
+ "studio/test/monkeyrunner/index.html",
+ "studio/test/command-line.html",
"https://source.android.com/devices/tech/debug/dumpsys.html"
]
},
@@ -4663,7 +4906,7 @@
"distribute/essentials/quality/core.html",
"distribute/essentials/quality/tablets.html",
"distribute/tools/launch-checklist.html",
- "tools/publishing/publishing_overview.html",
+ "studio/publish/index.html",
"distribute/tools/localization-checklist.html"
]
},
@@ -4684,7 +4927,7 @@
"distribute/tools/promote/device-art.html",
"distribute/tools/promote/linking.html",
"distribute/tools/promote/brand.html",
- "tools/help/proguard.html"
+ "studio/build/shrink-code.html"
]
},
"overview/4": {
@@ -4719,65 +4962,65 @@
"tools/help/log": {
"title": "",
"resources": [
- "tools/help/am-logcat.html"
+ "studio/debug/am-logcat.html"
]
},
"tools/help/monitor": {
"title": "",
"resources": [
- "tools/help/am-memory.html",
- "tools/help/am-cpu.html",
- "tools/help/am-gpu.html",
- "tools/help/am-network.html"
+ "studio/profile/am-memory.html",
+ "studio/profile/am-cpu.html",
+ "studio/profile/am-gpu.html",
+ "studio/profile/am-network.html"
]
},
"tools/help/data": {
"title": "",
"resources": [
- "tools/help/am-hprof.html",
- "tools/help/am-allocation.html",
- "tools/help/am-methodtrace.html",
- "tools/help/am-sysinfo.html"
+ "studio/profile/am-hprof.html",
+ "studio/profile/am-allocation.html",
+ "studio/profile/am-methodtrace.html",
+ "studio/profile/am-sysinfo.html"
]
},
"tools/help/shot": {
"title": "",
"resources": [
- "tools/help/am-screenshot.html",
- "tools/help/am-video.html"
+ "studio/debug/am-screenshot.html",
+ "studio/debug/am-video.html"
]
},
"tools/performance/rendering": {
"title": "",
"resources": [
- "tools/performance/debug-gpu-overdraw/index.html",
- "tools/performance/profile-gpu-rendering/index.html",
- "tools/performance/hierarchy-viewer/setup.html",
- "tools/performance/hierarchy-viewer/index.html",
- "tools/performance/hierarchy-viewer/profiling.html"
+ "studio/profile/dev-options-overdraw.html",
+ "studio/profile/dev-options-rendering.html",
+ "studio/profile/hierarchy-viewer-setup.html",
+ "studio/profile/hierarchy-viewer-walkthru.html",
+ "studio/profile/hierarchy-viewer-results-walkthru.html"
]
},
"tools/performance/memory": {
"title": "",
"resources": [
- "tools/performance/memory-monitor/index.html",
- "tools/performance/heap-viewer/index.html",
- "tools/performance/allocation-tracker/index.html",
- "tools/performance/comparison.html"
+ "studio/tools/performance/memory-monitor/index.html",
+ "studio/profile/heap-viewer-walkthru.html",
+ "studio/profile/allocation-tracker-walkthru.html",
+ "studio/tools/performance/comparison.html"
]
},
"tools/performance/cpu": {
"title": "",
"resources": [
- "tools/performance/traceview/index.html",
- "tools/performance/systrace/index.html"
+ "studio/profile/traceview-walkthru.html",
+ "studio/profile/systrace-walkthru.html"
]
},
"tools/performance/battery": {
"title": "",
"resources": [
- "tools/performance/batterystats-battery-historian/index.html",
- "tools/performance/batterystats-battery-historian/charts.html"
+ "studio/profile/battery-historian.html",
+ "studio/profile/battery-historian-charts.html"
]
},
"marshmallow/landing/resources": {
@@ -4830,9 +5073,17 @@
"tools/landing/resources": {
"title": "",
"resources": [
- "tools/studio/index.html",
- "tools/studio/studio-features.html",
- "sdk/installing/studio-tips.html",
+ "studio/features.html",
+ "studio/intro/index.html",
+ "studio/build/index.html",
+ ]
+ },
+ "tools/landing/latest": {
+ "title": "",
+ "resources": [
+ "https://medium.com/google-developers/how-often-should-you-update-android-studio-db25785c488e#.8blbql35x",
+ "http://android-developers.blogspot.com/2016/04/android-studio-2-0.html",
+ "https://medium.com/google-developers/writing-more-code-by-writing-less-code-with-android-studio-live-templates-244f648d17c7#.hczcm02du",
]
},
"preview/landing/resources": {
diff --git a/docs/html/training/camera/photobasics.jd b/docs/html/training/camera/photobasics.jd
index efac5483..bfea0f7 100644
--- a/docs/html/training/camera/photobasics.jd
+++ b/docs/html/training/camera/photobasics.jd
@@ -175,7 +175,8 @@
</pre>
<p class="note"><strong>Note:</strong> Files you save in the directories provided by
-{@link android.content.Context#getExternalFilesDir getExternalFilesDir()} are deleted
+{@link android.content.Context#getExternalFilesDir getExternalFilesDir()} or
+{@link android.content.Context#getFilesDir getFilesDir()} are deleted
when the user uninstalls your app.</p>
<p>Once you decide the directory for the file, you need to create a
@@ -190,8 +191,7 @@
// Create an image file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "JPEG_" + timeStamp + "_";
- File storageDir = Environment.getExternalStoragePublicDirectory(
- Environment.DIRECTORY_PICTURES);
+ File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
File image = File.createTempFile(
imageFileName, /* prefix */
".jpg", /* suffix */
@@ -225,14 +225,66 @@
}
// Continue only if the File was successfully created
if (photoFile != null) {
- takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT,
- Uri.fromFile(photoFile));
+ Uri photoURI = FileProvider.getUriForFile(this,
+ "com.example.android.fileprovider",
+ photoFile);
+ takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
startActivityForResult(takePictureIntent, REQUEST_TAKE_PHOTO);
}
}
}
</pre>
+<p class="note"><strong>Note:</strong> We are using {@link
+android.support.v4.content.FileProvider#getUriForFile} which returns a <code>content://</code>
+URI. For more recent apps targeting Android N and higher, passing a <code>file://</code> URI
+across a package boundary causes a {@link android.os.FileUriExposedException
+FileUriExposedException}.
+Therefore, we now present a more generic way of storing images using a
+{@link android.support.v4.content.FileProvider FileProvider}.
+</p>
+
+Now, you need to configure the {@link android.support.v4.content.FileProvider
+FileProvider}. In your app's manifest, add a provider to your application:
+
+<pre>
+<application>
+ ...
+ <provider
+ android:name="android.support.v4.content.FileProvider"
+ android:authorities="com.example.android.fileprovider"
+ android:exported="false"
+ android:grantUriPermissions="true">
+ <meta-data
+ android:name="android.support.FILE_PROVIDER_PATHS"
+ android:resource="@xml/file_paths"></meta-data>
+ </provider>
+ ...
+</application>
+</pre>
+
+Make sure that the authorities string matches the second argument to {@link
+android.support.v4.content.FileProvider#getUriForFile}.
+In the meta-data section of the provider definition, you can see that
+the provider expects eligible paths to be configured in a dedicated resource file,
+<c>res/xml/file_paths.xml</c>. Here is the content required for this particular
+example:
+
+<pre>
+<?xml version="1.0" encoding="utf-8"?>
+<paths xmlns:android="http://schemas.android.com/apk/res/android">
+ <external-path name="my_images" path="Android/data/com.example.package.name/files/Pictures" />
+</paths>
+</pre>
+
+The path component corresponds to the path that is returned by
+{@link android.content.Context#getExternalFilesDir getExternalFilesDir()}
+when called with {@link android.os.Environment#DIRECTORY_PICTURES
+Environment.DIRECTORY_PICTURES}. Make sure that you replace
+<code>com.example.package.name</code> with the actual package name of your
+app. Also, checkout the documentation of {@link android.support.v4.content.FileProvider} for
+an extensive description of path specifiers that you can use besides
+<code>external-path</code>.
<h2 id="TaskGallery">Add the Photo to a Gallery</h2>
diff --git a/docs/html/wear/preview/_book.yaml b/docs/html/wear/preview/_book.yaml
new file mode 100644
index 0000000..ddcfc11
--- /dev/null
+++ b/docs/html/wear/preview/_book.yaml
@@ -0,0 +1,25 @@
+toc:
+- title: Wear Developer Preview
+ path: /wear/preview/index.html
+
+- title: Program Overview
+ path: /wear/preview/program.html
+
+- title: API Overview
+ path: /wear/preview/api-overview.html
+ section:
+ - title: Expanded Notifications
+ path: /wear/preview/features/notifications.html
+ - title: Complications
+ path: /wear/preview/features/complications.html
+ - title: Wear Navigation and Actions
+ path: /wear/preview/features/ui-nav-actions.html
+
+- title: Downloads
+ path: /wear/preview/downloads.html
+
+- title: Get Started
+ path: /wear/preview/start.html
+
+- title: License Agreement
+ path: /wear/preview/license.html
diff --git a/docs/html/wear/preview/api-overview.jd b/docs/html/wear/preview/api-overview.jd
new file mode 100644
index 0000000..bf18c16
--- /dev/null
+++ b/docs/html/wear/preview/api-overview.jd
@@ -0,0 +1,124 @@
+page.title=Preview API Overview
+meta.tags="wear", "wear-preview"
+page.tags="wear"
+page.image=images/cards/card-n-apis_2x.png
+@jd:body
+
+
+
+
+<div id="qv-wrapper">
+<div id="qv">
+ <h2>Key developer features</h2>
+ <ol>
+ <ul style="list-style-type:none;">
+ <li><a href="#stand-alone">Stand Alone Devices</a>
+ <ol>
+ <li><a href="#wear-apk">Wear-Specific APKs</a></li>
+ <li><a href="#network">Network Access</a></li>
+ <li><a href="#auth">Authentication</a></li>
+ </ol>
+ </li>
+ <li><a href="#notify">Notifications and Interactions</a>
+ <ol>
+ <li><a href="#appoid">Appoids with Chat Templates</a></li>
+ <li><a href="#smart-replies">Smart Replies</a></li>
+ <li><a href="#remote-input">Remote Input</a></li>
+ <li><a href="#imf">Input Method Framework</a></li>
+ </ol>
+ </li>
+ <li><a href="#ui">User Interface Improvements</a>
+ <ol>
+ <li><a href="#complicatiosn">Complications</a></li>
+ <li><a href="#drawers">Navigation and Action Drawers</a></li>
+ <li><a href="#button-loc">Button Locations</a></li>
+ </ol>
+ </li>
+ </ol>
+</div>
+</div>
+
+
+
+<p>
+ The Android Wear Preview API is still in active development, but you can try
+ it now as part of the Wear 2.0 Developer Preview. The sections below
+ highlight some of the new features for Wear developers.
+</p>
+
+
+<h2 id="stand-alone">Stand Alone Devices</h2>
+
+<p>Description of developer theme</p>
+
+<h3 id="wear-apk">Wear-Specific APKs</h3>
+
+<p>Description of feature</p>
+
+<p>Sample implementation of feature</p>
+
+<h3 id="network">Network Access</h3>
+
+<p>Description of feature</p>
+
+<p>Sample implementation of feature</p>
+
+<h3 id="auth">Authentication</h3>
+
+<p>Description of feature</p>
+
+<p>Sample implementation of feature</p>
+
+
+
+<h2 id="notify">Notifications and Interactions</h2>
+
+<p>Description of developer theme</p>
+
+<h3 id="appoid">Appoids with Chat Templates</h3>
+
+<p>Description of feature</p>
+
+<p>Sample implementation of feature</p>
+
+<h3 id="smart-replies">Smart Replies</h3>
+
+<p>Description of feature</p>
+
+<p>Sample implementation of feature</p>
+
+<h3 id="remote-input">Remote Input</h3>
+
+<p>Description of feature</p>
+
+<p>Sample implementation of feature</p>
+
+<h3 id="imf">Input Method Framework</h3>
+
+<p>Description of feature</p>
+
+<p>Sample implementation of feature</p>
+
+
+
+<h2 id="ui">User Interface Improvements</h2>
+
+<p>Description of developer theme</p>
+
+<h3 id="complicatiosn">Complications</h3>
+
+<p>Description of feature</p>
+
+<p>Sample implementation of feature</p>
+
+<h3 id="drawers">Navigation and Action Drawers</h3>
+
+<p>Description of feature</p>
+
+<p>Sample implementation of feature</p>
+
+<h3 id="button-loc">Button Locations</h3>
+
+<p>Description of feature</p>
+
+<p>Sample implementation of feature</p>
diff --git a/docs/html/wear/preview/downloads.jd b/docs/html/wear/preview/downloads.jd
new file mode 100644
index 0000000..10c1377
--- /dev/null
+++ b/docs/html/wear/preview/downloads.jd
@@ -0,0 +1,457 @@
+page.title=Preview Downloads
+meta.tags="wear-preview", "system image", "download"
+page.tags="wear"
+page.image=images/cards/card-n-downloads_2x.png
+
+@jd:body
+
+<div style="position:relative; min-height:600px">
+
+ <div class="wrap" id="tos" style="position:absolute;display:none;width:inherit;">
+
+ <p class="sdk-terms-intro">Before downloading and installing components of
+ the Android Wear Preview SDK, you must agree to the following terms and
+ conditions.</p>
+
+ <h2 class="norule">Terms and Conditions</h2>
+
+ <div class="sdk-terms" onfocus="this.blur()" style="width:678px">
+This is the Android Wear SDK Preview License Agreement (the “License Agreement”).
+
+1. Introduction
+
+1.1 The Android Wear SDK Preview (referred to in the License Agreement as the “Preview” and specifically including the Android system files, packaged APIs, and Preview library files, if and when they are made available) is licensed to you subject to the terms of the License Agreement. The License Agreement forms a legally binding contract between you and Google in relation to your use of the Preview.
+
+1.2 "Android" means the Android software stack for devices, as made available under the Android Open Source Project, which is located at the following URL: http://source.android.com/, as updated from time to time.
+
+1.3 “Android-compatible” means any Android implemation that (i) complies with the Android Compatibility Definition document, which can be found at the Android compatibility website (http://source.android.com/compatibility) and which may be updated from time to time; and (ii) successfully passes the Android Compatibility Test Suite (CTS).
+
+1.4 "Google" means Google Inc., a Delaware corporation with principal place of business at 1600 Amphitheatre Parkway, Mountain View, CA 94043, United States.
+
+2. Accepting the License Agreement
+
+2.1 In order to use the Preview, you must first agree to the License Agreement. You may not use the Preview if you do not accept the License Agreement.
+
+2.2 By clicking to accept and/or using the Preview, you hereby agree to the terms of the License Agreement.
+
+2.3 You may not use the Preview and may not accept the License Agreement if you are a person barred from receiving the Preview under the laws of the United States or other countries including the country in which you are resident or from which you use the Preview.
+
+2.4 If you will use the Preview internally within your company or organization you agree to be bound by the License Agreement on behalf of your employer or other entity, and you represent and warrant that you have full legal authority to bind your employer or such entity to the License Agreement. If you do not have the requisite authority, you may not accept the License Agreement or use the Preview on behalf of your employer or other entity.
+
+3. Preview License from Google
+
+3.1 Subject to the terms of this License Agreement, Google grants you a limited, worldwide, royalty-free, non-assignable, non-exclusive, and non-sublicensable license to use the Preview solely to develop applications for compatible implementations of Android.
+
+3.2 You may not use this Preview to develop applications for other platforms (including non-compatible implementations of Android) or to develop another SDK. You are of course free to develop applications for other platforms, including non-compatible implementations of Android, provided that this Preview is not used for that purpose.
+
+3.3 You agree that Google or third parties owns all legal right, title and interest in and to the Preview, including any Intellectual Property Rights that subsist in the Preview. "Intellectual Property Rights" means any and all rights under patent law, copyright law, trade secret law, trademark law, and any and all other proprietary rights. Google reserves all rights not expressly granted to you.
+
+3.4 You may not use the Preview for any purpose not expressly permitted by the License Agreement. Except to the extent required by applicable third party licenses, you may not: (a) copy (except for backup purposes), modify, adapt, redistribute, decompile, reverse engineer, disassemble, or create derivative works of the Preview or any part of the Preview; or (b) load any part of the Preview onto a mobile handset or any other hardware device except a personal computer, combine any part of the Preview with other software, or distribute any software or device incorporating a part of the Preview.
+
+3.5 Use, reproduction and distribution of components of the Preview licensed under an open source software license are governed solely by the terms of that open source software license and not the License Agreement. You agree to remain a licensee in good standing in regard to such open source software licenses under all the rights granted and to refrain from any actions that may terminate, suspend, or breach such rights.
+
+3.6 You agree that the form and nature of the Preview that Google provides may change without prior notice to you and that future versions of the Preview may be incompatible with applications developed on previous versions of the Preview. You agree that Google may stop (permanently or temporarily) providing the Preview (or any features within the Preview) to you or to users generally at Google's sole discretion, without prior notice to you.
+
+3.7 Nothing in the License Agreement gives you a right to use any of Google's trade names, trademarks, service marks, logos, domain names, or other distinctive brand features.
+
+3.8 You agree that you will not remove, obscure, or alter any proprietary rights notices (including copyright and trademark notices) that may be affixed to or contained within the Preview.
+
+4. Use of the Preview by You
+
+4.1 Google agrees that nothing in the License Agreement gives Google any right, title or interest from you (or your licensors) under the License Agreement in or to any software applications that you develop using the Preview, including any intellectual property rights that subsist in those applications.
+
+4.2 You agree to use the Preview and write applications only for purposes that are permitted by (a) the License Agreement, and (b) any applicable law, regulation or generally accepted practices or guidelines in the relevant jurisdictions (including any laws regarding the export of data or software to and from the United States or other relevant countries).
+
+4.3 You agree that if you use the Preview to develop applications, you will protect the privacy and legal rights of users. If users provide you with user names, passwords, or other login information or personal information, you must make the users aware that the information will be available to your application, and you must provide legally adequate privacy notice and protection for those users. If your application stores personal or sensitive information provided by users, it must do so securely. If users provide you with Google Account information, your application may only use that information to access the user's Google Account when, and for the limited purposes for which, each user has given you permission to do so.
+
+4.4 You agree that you will not engage in any activity with the Preview, including the development or distribution of an application, that interferes with, disrupts, damages, or accesses in an unauthorized manner the servers, networks, or other properties or services of Google or any third party.
+
+4.5 You agree that you are solely responsible for (and that Google has no responsibility to you or to any third party for) any data, content, or resources that you create, transmit or display through Android and/or applications for Android, and for the consequences of your actions (including any loss or damage which Google may suffer) by doing so.
+
+4.6 You agree that you are solely responsible for (and that Google has no responsibility to you or to any third party for) any breach of your obligations under the License Agreement, any applicable third party contract or Terms of Service, or any applicable law or regulation, and for the consequences (including any loss or damage which Google or any third party may suffer) of any such breach.
+
+4.7 The Preview is in development, and your testing and feedback are an important part of the development process. By using the Preview, you acknowledge that implementation of some features are still under development and that you should not rely on the Preview having the full functionality of a stable release. You agree not to publicly distribute or ship any application using this Preview as this Preview will no longer be supported after the official Android SDK is released.
+
+5. Your Developer Credentials
+
+5.1 You agree that you are responsible for maintaining the confidentiality of any developer credentials that may be issued to you by Google or which you may choose yourself and that you will be solely responsible for all applications that are developed under your developer credentials.
+
+6. Privacy and Information
+
+6.1 In order to continually innovate and improve the Preview, Google may collect certain usage statistics from the software including but not limited to a unique identifier, associated IP address, version number of the software, and information on which tools and/or services in the Preview are being used and how they are being used. Before any of this information is collected, the Preview will notify you and seek your consent. If you withhold consent, the information will not be collected.
+
+6.2 The data collected is examined in the aggregate to improve the Preview and is maintained in accordance with Google's Privacy Policy located at http://www.google.com/policies/privacy/.
+
+7. Third Party Applications
+
+7.1 If you use the Preview to run applications developed by a third party or that access data, content or resources provided by a third party, you agree that Google is not responsible for those applications, data, content, or resources. You understand that all data, content or resources which you may access through such third party applications are the sole responsibility of the person from which they originated and that Google is not liable for any loss or damage that you may experience as a result of the use or access of any of those third party applications, data, content, or resources.
+
+7.2 You should be aware the data, content, and resources presented to you through such a third party application may be protected by intellectual property rights which are owned by the providers (or by other persons or companies on their behalf). You may not modify, rent, lease, loan, sell, distribute or create derivative works based on these data, content, or resources (either in whole or in part) unless you have been specifically given permission to do so by the relevant owners.
+
+7.3 You acknowledge that your use of such third party applications, data, content, or resources may be subject to separate terms between you and the relevant third party.
+
+8. Using Google APIs
+
+8.1 Google APIs
+
+8.1.1 If you use any API to retrieve data from Google, you acknowledge that the data may be protected by intellectual property rights which are owned by Google or those parties that provide the data (or by other persons or companies on their behalf). Your use of any such API may be subject to additional Terms of Service. You may not modify, rent, lease, loan, sell, distribute or create derivative works based on this data (either in whole or in part) unless allowed by the relevant Terms of Service.
+
+8.1.2 If you use any API to retrieve a user's data from Google, you acknowledge and agree that you shall retrieve data only with the user's explicit consent and only when, and for the limited purposes for which, the user has given you permission to do so.
+
+9. Terminating the License Agreement
+
+9.1 the License Agreement will continue to apply until terminated by either you or Google as set out below.
+
+9.2 If you want to terminate the License Agreement, you may do so by ceasing your use of the Preview and any relevant developer credentials.
+
+9.3 Google may at any time, terminate the License Agreement, with or without cause, upon notice to you.
+
+9.4 The License Agreement will automatically terminate without notice or other action upon the earlier of:
+(A) when Google ceases to provide the Preview or certain parts of the Preview to users in the country in which you are resident or from which you use the service; and
+(B) Google issues a final release version of the Android SDK.
+
+9.5 When the License Agreement is terminated, the license granted to you in the License Agreement will terminate, you will immediately cease all use of the Preview, and the provisions of paragraphs 10, 11, 12 and 14 shall survive indefinitely.
+
+10. DISCLAIMERS
+
+10.1 YOU EXPRESSLY UNDERSTAND AND AGREE THAT YOUR USE OF THE PREVIEW IS AT YOUR SOLE RISK AND THAT THE PREVIEW IS PROVIDED "AS IS" AND "AS AVAILABLE" WITHOUT WARRANTY OF ANY KIND FROM GOOGLE.
+
+10.2 YOUR USE OF THE PREVIEW AND ANY MATERIAL DOWNLOADED OR OTHERWISE OBTAINED THROUGH THE USE OF THE PREVIEW IS AT YOUR OWN DISCRETION AND RISK AND YOU ARE SOLELY RESPONSIBLE FOR ANY DAMAGE TO YOUR COMPUTER SYSTEM OR OTHER DEVICE OR LOSS OF DATA THAT RESULTS FROM SUCH USE. WITHOUT LIMITING THE FOREGOING, YOU UNDERSTAND THAT THE PREVIEW IS NOT A STABLE RELEASE AND MAY CONTAIN ERRORS, DEFECTS AND SECURITY VULNERABILITIES THAT CAN RESULT IN SIGNIFICANT DAMAGE, INCLUDING THE COMPLETE, IRRECOVERABLE LOSS OF USE OF YOUR COMPUTER SYSTEM OR OTHER DEVICE.
+
+10.3 GOOGLE FURTHER EXPRESSLY DISCLAIMS ALL WARRANTIES AND CONDITIONS OF ANY KIND, WHETHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES AND CONDITIONS OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+
+11. LIMITATION OF LIABILITY
+
+11.1 YOU EXPRESSLY UNDERSTAND AND AGREE THAT GOOGLE, ITS SUBSIDIARIES AND AFFILIATES, AND ITS LICENSORS SHALL NOT BE LIABLE TO YOU UNDER ANY THEORY OF LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, CONSEQUENTIAL OR EXEMPLARY DAMAGES THAT MAY BE INCURRED BY YOU, INCLUDING ANY LOSS OF DATA, WHETHER OR NOT GOOGLE OR ITS REPRESENTATIVES HAVE BEEN ADVISED OF OR SHOULD HAVE BEEN AWARE OF THE POSSIBILITY OF ANY SUCH LOSSES ARISING.
+
+12. Indemnification
+
+12.1 To the maximum extent permitted by law, you agree to defend, indemnify and hold harmless Google, its affiliates and their respective directors, officers, employees and agents from and against any and all claims, actions, suits or proceedings, as well as any and all losses, liabilities, damages, costs and expenses (including reasonable attorneys’ fees) arising out of or accruing from (a) your use of the Preview, (b) any application you develop on the Preview that infringes any Intellectual Property Rights of any person or defames any person or violates their rights of publicity or privacy, and (c) any non-compliance by you of the License Agreement.
+
+13. Changes to the License Agreement
+
+13.1 Google may make changes to the License Agreement as it distributes new versions of the Preview. When these changes are made, Google will make a new version of the License Agreement available on the website where the Preview is made available.
+
+14. General Legal Terms
+
+14.1 the License Agreement constitutes the whole legal agreement between you and Google and governs your use of the Preview (excluding any services which Google may provide to you under a separate written agreement), and completely replaces any prior agreements between you and Google in relation to the Preview.
+
+14.2 You agree that if Google does not exercise or enforce any legal right or remedy which is contained in the License Agreement (or which Google has the benefit of under any applicable law), this will not be taken to be a formal waiver of Google's rights and that those rights or remedies will still be available to Google.
+
+14.3 If any court of law, having the jurisdiction to decide on this matter, rules that any provision of the License Agreement is invalid, then that provision will be removed from the License Agreement without affecting the rest of the License Agreement. The remaining provisions of the License Agreement will continue to be valid and enforceable.
+
+14.4 You acknowledge and agree that each member of the group of companies of which Google is the parent shall be third party beneficiaries to the License Agreement and that such other companies shall be entitled to directly enforce, and rely upon, any provision of the License Agreement that confers a benefit on (or rights in favor of) them. Other than this, no other person or company shall be third party beneficiaries to the License Agreement.
+
+14.5 EXPORT RESTRICTIONS. THE PREVIEW IS SUBJECT TO UNITED STATES EXPORT LAWS AND REGULATIONS. YOU MUST COMPLY WITH ALL DOMESTIC AND INTERNATIONAL EXPORT LAWS AND REGULATIONS THAT APPLY TO THE PREVIEW. THESE LAWS INCLUDE RESTRICTIONS ON DESTINATIONS, END USERS AND END USE.
+
+14.6 The License Agreement may not be assigned or transferred by you without the prior written approval of Google, and any attempted assignment without such approval will be void. You shall not delegate your responsibilities or obligations under the License Agreement without the prior written approval of Google.
+
+14.7 The License Agreement, and your relationship with Google under the License Agreement, shall be governed by the laws of the State of California without regard to its conflict of laws provisions. You and Google agree to submit to the exclusive jurisdiction of the courts located within the county of Santa Clara, California to resolve any legal matter arising from the License Agreement. Notwithstanding this, you agree that Google shall still be allowed to apply for injunctive remedies (or an equivalent type of urgent legal relief) in any jurisdiction.
+ </div><!-- sdk terms -->
+
+
+
+ <div id="sdk-terms-form">
+ <p>
+ <input id="agree" type="checkbox" name="agree" value="1" onclick="onAgreeChecked()" />
+ <label id="agreeLabel" for="agree">I have read and agree with the above terms and conditions</label>
+ </p>
+ <p><a href="" class="button disabled" id="downloadForRealz" onclick="return onDownloadForRealz(this);"></a></p>
+ </div>
+
+
+ </div><!-- end TOS -->
+
+
+ <div id="landing">
+
+<div id="qv-wrapper">
+ <div id="qv">
+ <h2>In this document</h2>
+ <ol>
+ <li><a href="#device-preview">Set up a hardware device</a>
+ <ol>
+ <li><a href="#flash">Flash a device</a></li>
+ <li><a href="#revertDevice">Uninstalling the Preview</a></li>
+ </ol>
+ </li>
+ <li><a href="#setupAVD">Set up an emulator</a></li>
+ </ol>
+ </div>
+</div>
+
+<p>
+ To run and test your app with the Wear Developer Preview, you need to set up
+ a runtime environment. You can do that in either of these ways:
+</p>
+
+<ul>
+ <li>Install a Wear Preview system image on a supported hardware device,</li>
+ <li>Set up an Android emulator running the Wear Developer Preview</li>
+</ul>
+
+<p>
+ If you want an environment for basic compatibility testing of your app on the
+ new platform, all you need is your current APK and a hardware device or
+ emulator. You don't necessarily need to update your full development
+ environment to do basic testing.
+</p>
+
+<p>
+ If you want to modify your app to target the Wear Preview or use the Wear
+ Preview APIs, you need to set up a development environment that's updated
+ to support the Wear Preview. For more information, see
+ <a href="{@docRoot}wear/preview/start.html">Get Started with Wear Preview</a>.
+</p>
+
+
+<h2 id="downloads">Download Files</h2>
+
+
+
+<h3 id="docs-dl">Reference documentation</h3>
+
+<p>
+ Detailed information about the Wear Preview APIs is available in the
+ reference documentation, which you can download from the following table.
+ This package contains an abridged, offline version of the Android developer
+ web site, and includes an updated API reference for the Wear Preview APIs
+ and an API difference report.
+</p>
+
+<table>
+ <tr>
+ <th scope="col">Documentation</th>
+ <th scope="col">Checksums</th>
+ </tr>
+ <tr>
+ <td style="white-space: nowrap">
+ <a href="{@docRoot}shareables/preview/n-preview-1-docs.zip"
+ >n-preview-1-docs.zip</a></td>
+ <td width="100%">
+ MD5: 4ab33ccbe698f46f125cc5b807cf9c2f<br>
+ SHA-1: 6a3880b3ccd19614daae5a4d0698ea6ae11c20a5
+ </td>
+ </tr>
+<table>
+
+<h3 id="images-dl">Device system images</h3>
+
+<p>
+ The following device system images can be used to update a compatible device
+ with the Wear Preview for testing. For information on installing these
+ images, see <a href="#device-preview">Set up a Hardware Device</a>.
+</p>
+
+<table>
+ <tr>
+ <th scope="col">Device</th>
+ <th scope="col">Download / Checksums</th>
+ </tr>
+
+ <tr id="sprat">
+ <td>Gear Live <br>"sprat"</td>
+ <td><a href="#top" onclick="onDownload(this)"
+ >sprat-XXXXX-preview-d86c7559.tgz</a><br>
+ MD5: d84b6c31a7754e505149594887b3481a<br>
+ SHA-1: d86c7559c93724cca6af91040b012c48529f2c94
+ </td>
+ </tr>
+
+</table>
+
+
+
+<h2 id="device-preview">Set up a Hardware Device</h2>
+
+<p>
+ The Wear Developer Preview offers system updates for a range of hardware devices
+ that you can use for testing your app, from phones to tablets and TV.
+</p>
+
+
+
+<h3 id="flash">Flash a device</h3>
+
+<p>
+ At any time you can download the latest Developer Preview system image and
+ manually flash it to your device. See the table below to download the system
+ image for your test device. Manually flashing a device is useful if you need
+ precise control over the test environment or need to reinstall frequently,
+ such as for automated testing.
+</p>
+
+<p>
+ Installing a system image on a device <strong>removes all data from the
+ device</strong>, so you should back up your data first.
+</p>
+
+<p>
+ After you back up your device data and download the system image below that
+ matches your device, follow the instructions at <a href=
+ "https://developers.google.com/android/nexus/images#instructions">developers.google.com/android</a>
+ to flash the image onto your device.
+</p>
+
+
+<h3 id="revertDevice">Uninstalling the Preview</h3>
+
+<p>
+ If you want to uninstall the preview from a device, you can do so in one of
+ these ways: </p>
+ <ul>
+ <li><strong>Obtain a factory spec system image</strong> and then manually
+ flash it to the device.
+ <ul>
+ <li>For <strong>Nexus devices and Pixel C devices</strong>, see
+ the <a href="http://developers.google.com/android/nexus/images">Factory Images
+ for Nexus Devices</a> page for downloads. </li>
+ <li>For <strong>other devices</strong>, please contact the device manufacturer
+ directly. Alternatively, if the device is supported
+ in the Android Beta Program, you can enroll the device in the
+ program and then un-enroll it (see below).</li>
+ </ul>
+ </li>
+ <li><strong>Un-enroll the device from Android Beta Program</strong>. If the
+ device is enrolled in the <a href="https://g.co/androidbeta">Android Beta
+ Program</a>, regardless of device, you can simply un-enroll it from the program.
+ <p>
+ The device will receive an OTA update to the most recent production version
+ of Android available for that device (for example, Android 6.0 Marshmallow).
+ The update requires a full device reset, so user data on the device will be
+ removed. Make sure to <strong>back up important data</strong> before
+ un-enrolling a device.
+ </p>
+ </li>
+</ul>
+
+<p class="note"><strong>Note:</strong>
+ Uninstalling a Developer Preview system image prior to
+ the end of the program requires a full device reset and removes all user data
+ on the device.
+</p>
+
+
+<h2 id="setupAVD">Set up an emulator</h2>
+
+<p>To use the Android Emulator to run the Wear Preview, you need to
+download the Wear Preview SDK and create a virtual device for the
+emulator.</p>
+
+<p>First, download the Wear Preview SDK as follows (if you
+already got it while <a href="{@docRoot}preview/setup-sdk.html">setting up
+to develop for Android N</a>, you can skip this part):
+
+<ol>
+ <li>In Android Studio, open the Settings dialog
+ (<strong>File > Settings</strong> on Windows/Linux, or
+ <strong>Android Studio > Preferences</strong> on Mac). In the left
+ panel, select <strong>Appearance & Behavior >
+ System Settings > Android SDK</strong>.
+
+ <li>Click the <strong>SDK Platforms</strong> tab, then select the
+ <strong>Wear Preview</strong> check box.</li>
+
+ <li>Click the <strong>SDK Tools</strong> tab, then select the
+ <strong>Android SDK Build Tools</strong>, <strong>Android SDK
+ Platform-Tools</strong>, and <strong>Android SDK Tools</strong> check
+ boxes.
+ </li>
+
+ <li>Click <strong>OK</strong> and accept the license
+ agreements for any packages to be installed.
+ </li>
+</ol>
+
+<p>You should now have <strong>Android SDK Built-Tools 24.0 0 rc1</strong>,
+<strong>Platform-Tools 24.0.0 rc1</strong>, and <strong>SDK Tools
+25.0.9</strong>. If you do not update the SDK Tools to 25.0.9, then you won't
+be able to run the x86_64 system images for Android N.</p>
+
+
+<p>Now create a virtual device with the Wear Preview system image:</p>
+
+<ol>
+ <li>Open the AVD Manager by selecting <strong>Tools > Android >
+ AVD Manager</strong>.</li>
+ <li>Click <strong>Create Virtual Device</strong>.</li>
+ <li>Select a device such as Nexus 5X, Nexus 6P, Nexus 9, or Android TV,
+ then click <strong>Next</strong>.</li>
+ <li>Select the <strong>N</strong> system image (with the
+ <strong>x86</strong> ABI), then click <strong>Next</strong>.
+ (Only x86 system images are currently supported with the Android Emulator
+for the Wear Preview.)
+ <li>Complete the rest of the AVD configuration and click
+ <strong>Finish</strong>.</li>
+</ol>
+
+<p>You can now launch the Android Emulator with the Wear Preview AVD.</p>
+
+<p>
+For the best experience in the Android Emulator, install
+Android Studio 2.2 Preview, which supports the <a
+href="http://tools.android.com/tech-docs/emulator">Android Emulator 2.0 Beta</a>
+with much faster performance compared to the Emulator in
+Android Studio 1.5.</p>
+
+<p>For more information about creating virtual devices, see <a href=
+ "{@docRoot}tools/devices/index.html">Managing Virtual Devices</a>.
+</p>
+
+
+
+ </div><!-- landing -->
+
+</div><!-- relative wrapper -->
+
+
+
+<script>
+ var urlRoot = "http://storage.googleapis.com/androiddevelopers/shareables/wear/preview/";
+ function onDownload(link) {
+
+ $("#downloadForRealz").html("Download " + $(link).text());
+ $("#downloadForRealz").attr('href', urlRoot + $(link).text());
+
+ $("#tos").fadeIn('fast');
+ $("#landing").fadeOut('fast');
+
+ return true;
+ }
+
+
+ function onAgreeChecked() {
+ /* verify that the TOS is agreed */
+ if ($("input#agree").is(":checked")) {
+ /* reveal the download button */
+ $("a#downloadForRealz").removeClass('disabled');
+ } else {
+ $("a#downloadForRealz").addClass('disabled');
+ }
+ }
+
+ function onDownloadForRealz(link) {
+ if ($("input#agree").is(':checked')) {
+ /*
+ $("#tos").fadeOut('fast');
+ $("#landing").fadeIn('fast');
+ */
+
+ ga('send', 'event', 'M Preview', 'System Image', $("#downloadForRealz").html());
+
+ /*
+ location.hash = "";
+ */
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ $(window).hashchange( function(){
+ if (location.hash == "") {
+ location.reload();
+ }
+ });
+
+</script>
diff --git a/docs/html/wear/preview/features/complications.jd b/docs/html/wear/preview/features/complications.jd
new file mode 100644
index 0000000..3d88f3a
--- /dev/null
+++ b/docs/html/wear/preview/features/complications.jd
@@ -0,0 +1,7 @@
+page.title=Watch Face Complications
+meta.tags="wear", "wear-preview", "complications"
+page.tags="wear"
+
+@jd:body
+
+<p>stub</p>
\ No newline at end of file
diff --git a/docs/html/wear/preview/features/ime.jd b/docs/html/wear/preview/features/ime.jd
new file mode 100644
index 0000000..dc4adf1
--- /dev/null
+++ b/docs/html/wear/preview/features/ime.jd
@@ -0,0 +1,7 @@
+page.title=Wear Input Method Framework
+meta.tags="wear", "wear-preview", "input-method", "ime"
+page.tags="wear"
+
+@jd:body
+
+<p>stub</p>
\ No newline at end of file
diff --git a/docs/html/wear/preview/features/notifications.jd b/docs/html/wear/preview/features/notifications.jd
new file mode 100644
index 0000000..21a77c2
--- /dev/null
+++ b/docs/html/wear/preview/features/notifications.jd
@@ -0,0 +1,7 @@
+page.title=Expanded Notifications
+meta.tags="wear", "wear-preview", "notifications"
+page.tags="wear"
+
+@jd:body
+
+<p>stub</p>
\ No newline at end of file
diff --git a/docs/html/wear/preview/features/ui-nav-actions.jd b/docs/html/wear/preview/features/ui-nav-actions.jd
new file mode 100644
index 0000000..ad61b98
--- /dev/null
+++ b/docs/html/wear/preview/features/ui-nav-actions.jd
@@ -0,0 +1,7 @@
+page.title=Wear Navigation and Actions
+meta.tags="wear", "wear-preview", "navigation", "action"
+page.tags="wear"
+
+@jd:body
+
+<p>stub</p>
\ No newline at end of file
diff --git a/docs/html/wear/preview/images/hero-1x.png b/docs/html/wear/preview/images/hero-1x.png
new file mode 100644
index 0000000..cde76c3
--- /dev/null
+++ b/docs/html/wear/preview/images/hero-1x.png
Binary files differ
diff --git a/docs/html/wear/preview/images/hero-2x.png b/docs/html/wear/preview/images/hero-2x.png
new file mode 100644
index 0000000..4d542d8
--- /dev/null
+++ b/docs/html/wear/preview/images/hero-2x.png
Binary files differ
diff --git a/docs/html/wear/preview/index.jd b/docs/html/wear/preview/index.jd
new file mode 100644
index 0000000..ff8d5bb
--- /dev/null
+++ b/docs/html/wear/preview/index.jd
@@ -0,0 +1,106 @@
+page.title=Android Wear 2.0 Developer Preview
+page.tags="wear","wear-preview"
+meta.tags="wear","preview"
+fullpage=true
+forcelocalnav=true
+header.hide=1
+footer.hide=1
+@jd:body
+
+<script>
+ $(document).ready(function() {
+ if (useUpdatedTemplates) {
+ $("#useUpdatedTemplates").css("display","block");
+ } else {
+ $("#useOldTemplates").css("display","block");
+ }
+ })
+</script>
+
+<section class="dac-expand dac-hero dac-light" style="background-color:#E1BEE7">
+ <div class="wrap" style="max-width:1100px;margin-top:0">
+ <div class="cols dac-hero-content" style="padding-bottom:1em;">
+
+ <div class="col-7of16 col-push-9of16" style="padding-left:2em">
+ <h1 class="dac-hero-title">Android Wear 2.0 Developer Preview</h1>
+ <p class="dac-hero-description">
+ Get ready for the next version of Android Wear!
+ Support stand-alone Wear devices and apps.
+ Create enhanced user interaction and glanceable experiences.
+ Test your apps on Wear devices.
+ </p>
+
+ <a class="dac-hero-cta" href="{@docRoot}wear/preview/program.html">
+ <span class="dac-sprite dac-auto-chevron"></span>
+ Learn more
+ </a>
+ </div>
+ <div class="col-9of16 col-pull-7of16 dac-hero-figure" style="margin-top:1.5em;padding-right:1.5em;">
+ <img class="dac-hero-image" src="{@docRoot}wear/preview/images/hero-1x.png"
+ srcset="{@docRoot}wear/preview/images/hero-1x.png 1x,
+ {@docRoot}wear/preview/images/hero-2x.png 2x">
+ </div>
+ </div>
+ <div class="dac-section dac-small">
+ <div class="resource-widget resource-flow-layout col-16"
+ data-query="collection:wear/preview/landing"
+ data-cardSizes="6x2"
+ data-maxResults="6"></div>
+ </div>
+ </div>
+</section>
+
+<div id="useUpdatedTemplates" style="display:none" class="dac-section dac-slim dac-gray dac-expand">
+ <div class="wrap dac-offset-parent">
+ <a class="dac-fab dac-scroll-button" data-scroll-button href="#build-apps">
+ <i class="dac-sprite dac-arrow-down-gray"></i>
+ </a>
+ <ul class="dac-actions">
+ <li class="dac-action">
+ <a class="dac-action-link" href="{@docRoot}wear/preview/bug">
+ <i class="dac-action-sprite dac-sprite dac-auto-chevron-large"></i>
+ Report an issue
+ </a>
+ </li>
+ <li class="dac-action">
+ <a class="dac-action-link" href="http://g.co/androidweardev">
+ <i class="dac-action-sprite dac-sprite dac-auto-chevron-large"></i>
+ Join developer community
+ </a>
+ </li>
+ </ul>
+ </div><!-- end .wrap -->
+</div><!-- end .dac-actions -->
+
+<div id="useOldTemplates" style="display:none;color:black" class="actions-bar dac-expand dac-invert">
+ <div class="wrap dac-offset-parent">
+
+ <div class="actions">
+ <div><a href="{@docRoot}wear/preview/bug">
+ <span class="dac-sprite dac-auto-chevron-large"></span>
+ Report an issue
+ </a></div>
+ <div><a href="http://g.co/androidweardev">
+ <span class="dac-sprite dac-auto-chevron-large"></span>
+ Join developer community
+ </a></div>
+ </div><!-- end .actions -->
+ </div><!-- end .wrap -->
+</div>
+
+<section class="dac-section dac-light"><div class="wrap">
+ <h1 class="dac-section-title">Resources</h1>
+ <div class="dac-section-subtitle">
+ Essential information to help you get your apps ready for the next version of Android Wear.
+ </div>
+
+ <div class="resource-widget resource-flow-layout col-16"
+ data-query="collection:wear/preview/landing/resources"
+ data-cardSizes="6x6"
+ data-items-per-page="6"
+ data-maxResults="15"
+ data-initial-results="6"></div>
+
+ </div>
+</section>
+
diff --git a/docs/html/wear/preview/license.jd b/docs/html/wear/preview/license.jd
new file mode 100644
index 0000000..e7a7547
--- /dev/null
+++ b/docs/html/wear/preview/license.jd
@@ -0,0 +1,145 @@
+page.title=License Agreement
+
+@jd:body
+
+<p>
+To get started with the Android Wear SDK Preview, you must agree to the following terms and conditions.
+As described below, please note that this is a preview version of the Android Wear SDK, subject to change, that you use at your own risk. The Android Wear SDK Preview is not a stable release, and may contain errors and defects that can result in serious damage to your computer systems, devices and data.
+</p>
+
+<p>
+This is the Android Wear SDK Preview License Agreement (the “License Agreement”).
+</p>
+<div class="sdk-terms" style="height:auto;border:0;padding:0;width:700px">
+1. Introduction
+
+1.1 The Android Wear SDK Preview (referred to in the License Agreement as the “Preview” and specifically including the Android system files, packaged APIs, and Preview library files, if and when they are made available) is licensed to you subject to the terms of the License Agreement. The License Agreement forms a legally binding contract between you and Google in relation to your use of the Preview.
+
+1.2 "Android" means the Android software stack for devices, as made available under the Android Open Source Project, which is located at the following URL: http://source.android.com/, as updated from time to time.
+
+1.3 “Android-compatible” means any Android implemation that (i) complies with the Android Compatibility Definition document, which can be found at the Android compatibility website (http://source.android.com/compatibility) and which may be updated from time to time; and (ii) successfully passes the Android Compatibility Test Suite (CTS).
+
+1.4 "Google" means Google Inc., a Delaware corporation with principal place of business at 1600 Amphitheatre Parkway, Mountain View, CA 94043, United States.
+
+2. Accepting the License Agreement
+
+2.1 In order to use the Preview, you must first agree to the License Agreement. You may not use the Preview if you do not accept the License Agreement.
+
+2.2 By clicking to accept and/or using the Preview, you hereby agree to the terms of the License Agreement.
+
+2.3 You may not use the Preview and may not accept the License Agreement if you are a person barred from receiving the Preview under the laws of the United States or other countries including the country in which you are resident or from which you use the Preview.
+
+2.4 If you will use the Preview internally within your company or organization you agree to be bound by the License Agreement on behalf of your employer or other entity, and you represent and warrant that you have full legal authority to bind your employer or such entity to the License Agreement. If you do not have the requisite authority, you may not accept the License Agreement or use the Preview on behalf of your employer or other entity.
+
+3. Preview License from Google
+
+3.1 Subject to the terms of this License Agreement, Google grants you a limited, worldwide, royalty-free, non-assignable, non-exclusive, and non-sublicensable license to use the Preview solely to develop applications for compatible implementations of Android.
+
+3.2 You may not use this Preview to develop applications for other platforms (including non-compatible implementations of Android) or to develop another SDK. You are of course free to develop applications for other platforms, including non-compatible implementations of Android, provided that this Preview is not used for that purpose.
+
+3.3 You agree that Google or third parties owns all legal right, title and interest in and to the Preview, including any Intellectual Property Rights that subsist in the Preview. "Intellectual Property Rights" means any and all rights under patent law, copyright law, trade secret law, trademark law, and any and all other proprietary rights. Google reserves all rights not expressly granted to you.
+
+3.4 You may not use the Preview for any purpose not expressly permitted by the License Agreement. Except to the extent required by applicable third party licenses, you may not: (a) copy (except for backup purposes), modify, adapt, redistribute, decompile, reverse engineer, disassemble, or create derivative works of the Preview or any part of the Preview; or (b) load any part of the Preview onto a mobile handset or any other hardware device except a personal computer, combine any part of the Preview with other software, or distribute any software or device incorporating a part of the Preview.
+
+3.5 Use, reproduction and distribution of components of the Preview licensed under an open source software license are governed solely by the terms of that open source software license and not the License Agreement. You agree to remain a licensee in good standing in regard to such open source software licenses under all the rights granted and to refrain from any actions that may terminate, suspend, or breach such rights.
+
+3.6 You agree that the form and nature of the Preview that Google provides may change without prior notice to you and that future versions of the Preview may be incompatible with applications developed on previous versions of the Preview. You agree that Google may stop (permanently or temporarily) providing the Preview (or any features within the Preview) to you or to users generally at Google's sole discretion, without prior notice to you.
+
+3.7 Nothing in the License Agreement gives you a right to use any of Google's trade names, trademarks, service marks, logos, domain names, or other distinctive brand features.
+
+3.8 You agree that you will not remove, obscure, or alter any proprietary rights notices (including copyright and trademark notices) that may be affixed to or contained within the Preview.
+
+4. Use of the Preview by You
+
+4.1 Google agrees that nothing in the License Agreement gives Google any right, title or interest from you (or your licensors) under the License Agreement in or to any software applications that you develop using the Preview, including any intellectual property rights that subsist in those applications.
+
+4.2 You agree to use the Preview and write applications only for purposes that are permitted by (a) the License Agreement, and (b) any applicable law, regulation or generally accepted practices or guidelines in the relevant jurisdictions (including any laws regarding the export of data or software to and from the United States or other relevant countries).
+
+4.3 You agree that if you use the Preview to develop applications, you will protect the privacy and legal rights of users. If users provide you with user names, passwords, or other login information or personal information, you must make the users aware that the information will be available to your application, and you must provide legally adequate privacy notice and protection for those users. If your application stores personal or sensitive information provided by users, it must do so securely. If users provide you with Google Account information, your application may only use that information to access the user's Google Account when, and for the limited purposes for which, each user has given you permission to do so.
+
+4.4 You agree that you will not engage in any activity with the Preview, including the development or distribution of an application, that interferes with, disrupts, damages, or accesses in an unauthorized manner the servers, networks, or other properties or services of Google or any third party.
+
+4.5 You agree that you are solely responsible for (and that Google has no responsibility to you or to any third party for) any data, content, or resources that you create, transmit or display through Android and/or applications for Android, and for the consequences of your actions (including any loss or damage which Google may suffer) by doing so.
+
+4.6 You agree that you are solely responsible for (and that Google has no responsibility to you or to any third party for) any breach of your obligations under the License Agreement, any applicable third party contract or Terms of Service, or any applicable law or regulation, and for the consequences (including any loss or damage which Google or any third party may suffer) of any such breach.
+
+4.7 The Preview is in development, and your testing and feedback are an important part of the development process. By using the Preview, you acknowledge that implementation of some features are still under development and that you should not rely on the Preview having the full functionality of a stable release. You agree not to publicly distribute or ship any application using this Preview as this Preview will no longer be supported after the official Android SDK is released.
+
+5. Your Developer Credentials
+
+5.1 You agree that you are responsible for maintaining the confidentiality of any developer credentials that may be issued to you by Google or which you may choose yourself and that you will be solely responsible for all applications that are developed under your developer credentials.
+
+6. Privacy and Information
+
+6.1 In order to continually innovate and improve the Preview, Google may collect certain usage statistics from the software including but not limited to a unique identifier, associated IP address, version number of the software, and information on which tools and/or services in the Preview are being used and how they are being used. Before any of this information is collected, the Preview will notify you and seek your consent. If you withhold consent, the information will not be collected.
+
+6.2 The data collected is examined in the aggregate to improve the Preview and is maintained in accordance with Google's Privacy Policy located at http://www.google.com/policies/privacy/.
+
+7. Third Party Applications
+
+7.1 If you use the Preview to run applications developed by a third party or that access data, content or resources provided by a third party, you agree that Google is not responsible for those applications, data, content, or resources. You understand that all data, content or resources which you may access through such third party applications are the sole responsibility of the person from which they originated and that Google is not liable for any loss or damage that you may experience as a result of the use or access of any of those third party applications, data, content, or resources.
+
+7.2 You should be aware the data, content, and resources presented to you through such a third party application may be protected by intellectual property rights which are owned by the providers (or by other persons or companies on their behalf). You may not modify, rent, lease, loan, sell, distribute or create derivative works based on these data, content, or resources (either in whole or in part) unless you have been specifically given permission to do so by the relevant owners.
+
+7.3 You acknowledge that your use of such third party applications, data, content, or resources may be subject to separate terms between you and the relevant third party.
+
+8. Using Google APIs
+
+8.1 Google APIs
+
+8.1.1 If you use any API to retrieve data from Google, you acknowledge that the data may be protected by intellectual property rights which are owned by Google or those parties that provide the data (or by other persons or companies on their behalf). Your use of any such API may be subject to additional Terms of Service. You may not modify, rent, lease, loan, sell, distribute or create derivative works based on this data (either in whole or in part) unless allowed by the relevant Terms of Service.
+
+8.1.2 If you use any API to retrieve a user's data from Google, you acknowledge and agree that you shall retrieve data only with the user's explicit consent and only when, and for the limited purposes for which, the user has given you permission to do so.
+
+9. Terminating the License Agreement
+
+9.1 the License Agreement will continue to apply until terminated by either you or Google as set out below.
+
+9.2 If you want to terminate the License Agreement, you may do so by ceasing your use of the Preview and any relevant developer credentials.
+
+9.3 Google may at any time, terminate the License Agreement, with or without cause, upon notice to you.
+
+9.4 The License Agreement will automatically terminate without notice or other action upon the earlier of:
+(A) when Google ceases to provide the Preview or certain parts of the Preview to users in the country in which you are resident or from which you use the service; and
+(B) Google issues a final release version of the Android SDK.
+
+9.5 When the License Agreement is terminated, the license granted to you in the License Agreement will terminate, you will immediately cease all use of the Preview, and the provisions of paragraphs 10, 11, 12 and 14 shall survive indefinitely.
+
+10. DISCLAIMERS
+
+10.1 YOU EXPRESSLY UNDERSTAND AND AGREE THAT YOUR USE OF THE PREVIEW IS AT YOUR SOLE RISK AND THAT THE PREVIEW IS PROVIDED "AS IS" AND "AS AVAILABLE" WITHOUT WARRANTY OF ANY KIND FROM GOOGLE.
+
+10.2 YOUR USE OF THE PREVIEW AND ANY MATERIAL DOWNLOADED OR OTHERWISE OBTAINED THROUGH THE USE OF THE PREVIEW IS AT YOUR OWN DISCRETION AND RISK AND YOU ARE SOLELY RESPONSIBLE FOR ANY DAMAGE TO YOUR COMPUTER SYSTEM OR OTHER DEVICE OR LOSS OF DATA THAT RESULTS FROM SUCH USE. WITHOUT LIMITING THE FOREGOING, YOU UNDERSTAND THAT THE PREVIEW IS NOT A STABLE RELEASE AND MAY CONTAIN ERRORS, DEFECTS AND SECURITY VULNERABILITIES THAT CAN RESULT IN SIGNIFICANT DAMAGE, INCLUDING THE COMPLETE, IRRECOVERABLE LOSS OF USE OF YOUR COMPUTER SYSTEM OR OTHER DEVICE.
+
+10.3 GOOGLE FURTHER EXPRESSLY DISCLAIMS ALL WARRANTIES AND CONDITIONS OF ANY KIND, WHETHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES AND CONDITIONS OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+
+11. LIMITATION OF LIABILITY
+
+11.1 YOU EXPRESSLY UNDERSTAND AND AGREE THAT GOOGLE, ITS SUBSIDIARIES AND AFFILIATES, AND ITS LICENSORS SHALL NOT BE LIABLE TO YOU UNDER ANY THEORY OF LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, CONSEQUENTIAL OR EXEMPLARY DAMAGES THAT MAY BE INCURRED BY YOU, INCLUDING ANY LOSS OF DATA, WHETHER OR NOT GOOGLE OR ITS REPRESENTATIVES HAVE BEEN ADVISED OF OR SHOULD HAVE BEEN AWARE OF THE POSSIBILITY OF ANY SUCH LOSSES ARISING.
+
+12. Indemnification
+
+12.1 To the maximum extent permitted by law, you agree to defend, indemnify and hold harmless Google, its affiliates and their respective directors, officers, employees and agents from and against any and all claims, actions, suits or proceedings, as well as any and all losses, liabilities, damages, costs and expenses (including reasonable attorneys’ fees) arising out of or accruing from (a) your use of the Preview, (b) any application you develop on the Preview that infringes any Intellectual Property Rights of any person or defames any person or violates their rights of publicity or privacy, and (c) any non-compliance by you of the License Agreement.
+
+13. Changes to the License Agreement
+
+13.1 Google may make changes to the License Agreement as it distributes new versions of the Preview. When these changes are made, Google will make a new version of the License Agreement available on the website where the Preview is made available.
+
+14. General Legal Terms
+
+14.1 the License Agreement constitutes the whole legal agreement between you and Google and governs your use of the Preview (excluding any services which Google may provide to you under a separate written agreement), and completely replaces any prior agreements between you and Google in relation to the Preview.
+
+14.2 You agree that if Google does not exercise or enforce any legal right or remedy which is contained in the License Agreement (or which Google has the benefit of under any applicable law), this will not be taken to be a formal waiver of Google's rights and that those rights or remedies will still be available to Google.
+
+14.3 If any court of law, having the jurisdiction to decide on this matter, rules that any provision of the License Agreement is invalid, then that provision will be removed from the License Agreement without affecting the rest of the License Agreement. The remaining provisions of the License Agreement will continue to be valid and enforceable.
+
+14.4 You acknowledge and agree that each member of the group of companies of which Google is the parent shall be third party beneficiaries to the License Agreement and that such other companies shall be entitled to directly enforce, and rely upon, any provision of the License Agreement that confers a benefit on (or rights in favor of) them. Other than this, no other person or company shall be third party beneficiaries to the License Agreement.
+
+14.5 EXPORT RESTRICTIONS. THE PREVIEW IS SUBJECT TO UNITED STATES EXPORT LAWS AND REGULATIONS. YOU MUST COMPLY WITH ALL DOMESTIC AND INTERNATIONAL EXPORT LAWS AND REGULATIONS THAT APPLY TO THE PREVIEW. THESE LAWS INCLUDE RESTRICTIONS ON DESTINATIONS, END USERS AND END USE.
+
+14.6 The License Agreement may not be assigned or transferred by you without the prior written approval of Google, and any attempted assignment without such approval will be void. You shall not delegate your responsibilities or obligations under the License Agreement without the prior written approval of Google.
+
+14.7 The License Agreement, and your relationship with Google under the License Agreement, shall be governed by the laws of the State of California without regard to its conflict of laws provisions. You and Google agree to submit to the exclusive jurisdiction of the courts located within the county of Santa Clara, California to resolve any legal matter arising from the License Agreement. Notwithstanding this, you agree that Google shall still be allowed to apply for injunctive remedies (or an equivalent type of urgent legal relief) in any jurisdiction.
+
+
+</div>
\ No newline at end of file
diff --git a/docs/html/wear/preview/preview_toc.cs b/docs/html/wear/preview/preview_toc.cs
new file mode 100644
index 0000000..f96bf1f
--- /dev/null
+++ b/docs/html/wear/preview/preview_toc.cs
@@ -0,0 +1,132 @@
+<ul id="nav">
+
+ <li class="nav-section">
+ <div class="nav-section-header empty"><a href="<?cs var:toroot ?>preview/overview.html"
+ es-lang="Información general del programa"
+ ja-lang="プログラム概要"
+ ko-lang="프로그램 개요"
+ pt-br-lang="Visão geral do programa"
+ ru-lang="Обзор программы"
+ zh-cn-lang="计划概览"
+ zh-tw-lang="程式總覽">
+ Program Overview</a></div>
+ </li>
+
+
+ <li class="nav-section">
+ <div class="nav-section-header empty"><a href="<?cs var:toroot ?>preview/support.html">
+ Support and Release Notes</a></div>
+ </li>
+
+ <li class="nav-section">
+ <div class="nav-section-header empty"><a href="<?cs var:toroot ?>preview/setup-sdk.html"
+ es-lang="Configurar el SDK de la versión preliminar"
+ ja-lang="Preview SDK のセットアップ"
+ ko-lang="미리 보기 SDK 설정하기"
+ pt-br-lang="Configuração do Preview SDK"
+ ru-lang="Настройка пакета SDK Preview"
+ zh-cn-lang="设置预览版 SDK"
+ zh-tw-lang="設定預覽版 SDK">
+ Set Up to Develop</a></div>
+ </li>
+ <li class="nav-section">
+ <div class="nav-section-header empty"><a href="<?cs var:toroot ?>preview/download.html">
+ Test on a Device</a></div>
+ </li>
+
+
+ <li class="nav-section">
+ <div class="nav-section-header"><a href="<?cs var:toroot ?>preview/behavior-changes.html"
+ es-lang="Cambios en los comportamientos"
+ ja-lang="動作の変更点"
+ ko-lang="동작 변경"
+ pt-br-lang="Mudanças de comportamento"
+ ru-lang="Изменения в работе"
+ zh-cn-lang="行为变更"
+ zh-tw-lang="行為變更">Behavior Changes
+ </a></div>
+ <ul>
+ <li><a href="<?cs var:toroot ?>preview/features/background-optimization.html"
+ >Background Optimizations</a></li>
+ <li><a href="<?cs var:toroot ?>preview/features/multilingual-support.html"
+ >Language and Locale</a></li>
+ </ul>
+ </li>
+
+ <li class="nav-section">
+ <div class="nav-section-header"><a href="<?cs var:toroot ?>preview/api-overview.html"
+ es-lang="Información general de la API"
+ ja-lang="API の概要"
+ ko-lang="API 개요"
+ pt-br-lang="Visão geral da API"
+ ru-lang="Обзор API-интерфейсов"
+ zh-cn-lang="API 概览"
+ zh-tw-lang="API 總覽">Android N for Developers
+ </a></div>
+ <ul>
+
+ <li><a href="<?cs var:toroot ?>preview/features/multi-window.html"
+ >Multi-Window Support</a></li>
+
+ <li><a href="<?cs var:toroot ?>preview/features/notification-updates.html"
+ >Notifications</a></li>
+
+ <li><a href="<?cs var:toroot ?>preview/features/data-saver.html"
+ >Data Saver</a></li>
+
+ <li><a href="<?cs var:toroot ?>preview/features/tv-recording-api.html"
+ >TV Recording</a></li>
+
+ <li><a href="<?cs var:toroot ?>preview/features/security-config.html"
+ >Network Security Configuration</a></li>
+
+ <li><a href="<?cs var:toroot ?>preview/features/icu4j-framework.html"
+ >ICU4J Support</a></li>
+
+ <li><a href="<?cs var:toroot ?>preview/j8-jack.html"
+ >Java 8 Language Features</a></li>
+
+ <li><a href="<?cs var:toroot ?>preview/features/afw.html"
+ >Android for Work Updates</a></li>
+ </ul>
+ </li>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <li class="nav-section">
+ <div class="nav-section-header empty"><a href="<?cs var:toroot ?>preview/samples.html"
+ es-lang="Ejemplos"
+ ja-lang="サンプル"
+ ko-lang="샘플"
+ pt-br-lang="Exemplos"
+ ru-lang="Примеры"
+ zh-cn-lang="示例"
+ zh-tw-lang="範例">
+ Samples</a></div>
+ </li>
+
+ <li class="nav-section">
+ <div class="nav-section-header empty"><a href="<?cs var:toroot ?>preview/license.html"
+ es-lang="Contrato de licencia"
+ ja-lang="使用許諾契約"
+ ko-lang="라이선스 계약"
+ pt-br-lang="Contrato de licença"
+ ru-lang="Лицензионное соглашение"
+ zh-cn-lang="许可协议"
+ zh-tw-lang="授權協議">
+ License Agreement</a></div>
+ </li>
+
+</ul>
diff --git a/docs/html/wear/preview/program.jd b/docs/html/wear/preview/program.jd
new file mode 100644
index 0000000..17df757
--- /dev/null
+++ b/docs/html/wear/preview/program.jd
@@ -0,0 +1,62 @@
+page.title=Preview Program Overview
+page.metaDescription=Get your apps ready for the next version of Android.
+page.image=images/cards/card-n-overview_2x.png
+meta.tags="wear", "wear-preview"
+page.tags="wear"
+
+@jd:body
+
+
+<p>
+ Welcome to the <strong>Wear Developer Preview</strong>, a program that
+ gives you everything you need to test and optimize your apps for the next
+ version of Android Wear. It's free, and you can get started right away just by
+ downloading the Wear Developer Preview tools.
+</p>
+
+
+
+<h2 id="timeline">Timeline and updates</h2>
+
+<p>
+ Lorem ipsum dolor sit amet, consul graecis gloriatur in cum. Porro noster ea
+ nam, omnes tollit facete ut vix. Ut nibh ancillae mei, unum mollis aliquid an
+ pri. No melius dignissim mel. An eum erant dicit volumus, ut eum animal
+ convenire.
+</p>
+
+
+<h2 id="preview_tools">What's in the Wear Developer Preview?</h2>
+
+<p>
+ Lorem ipsum dolor sit amet, consul graecis gloriatur in cum. Porro noster ea
+ nam, omnes tollit facete ut vix. Ut nibh ancillae mei, unum mollis aliquid an
+ pri. No melius dignissim mel. An eum erant dicit volumus, ut eum animal
+ convenire.
+</p>
+
+
+<h2 id="how_to_get_started">How to get started</h2>
+
+<p>
+ To get started testing your app with the Wear Developer Preview:
+</p>
+
+<ol>
+ <li> Review the <a href="{@docRoot}wear/preview/api-overview.html">API
+ Overview</a> to
+ get an idea of what's new and how it affects your apps.</li>
+ <li>Download the preview API documentation and system images from the
+ <a href="{@docRoot}wear/preview/downloads.html">Preview Downloads</a>
+ </li>
+ <li> Set up your environment by following the instructions for <a
+ href="{@docRoot}wear/preview/start.html">Get Started with Wear Preview</a>
+ and configuring test devices.</li>
+ <li> Join the <a href="http://g.co/androidweardev">Android Wear
+ Developer Community</a> to get the latest news and connect with other
+ developers working with the new platform.</li>
+</ol>
+
+<p>
+ Thank you for participating in the Android Wear Developer Preview program!
+</p>
diff --git a/docs/html/wear/preview/start.jd b/docs/html/wear/preview/start.jd
new file mode 100644
index 0000000..ff11700
--- /dev/null
+++ b/docs/html/wear/preview/start.jd
@@ -0,0 +1,139 @@
+page.title=Get Started with Wear Preview
+meta.keywords="wear-preview"
+page.tags="wear-preview"
+page.image=images/cards/card-n-sdk_2x.png
+
+@jd:body
+
+
+<div id="qv-wrapper">
+ <div id="qv">
+<ol>
+ <li><a href="#get-as22">Get Android Studio 2.2</a></li>
+ <li><a href="#get-sdk">Get the Wear Preview SDK</a></li>
+ <li><a href="#create-update">Update or Create a Project</a></li>
+</ol>
+ </div>
+</div>
+
+<p>
+ To develop apps for the Wear Developer Preview, you need to make some updates
+ to your developer environment. This page describes how to setup for testing
+ the Wear Preview APIs with your app.
+</p>
+
+
+<h2 id="get-as22">Get Android Studio 2.2 (preview)</h2>
+
+<p>
+ Android Studio 2.2 is currently available as a preview in the canary release
+ channel. If you already have Android Studio and don't want to update to the
+ canary channel, you can download Android Studio 2.2 as a separate
+ installation and use it for development with the Wear Developer Preview,
+ leaving your primary Android Studio environment unaffected.
+</p>
+
+<p>
+ To download Android Studio 2.2 as a separate installation, follow these steps
+ (or if you want to receive Android Studio 2.1 as an update to your existing
+ installation, skip to step 4):
+</p>
+
+<ol>
+ <li>Edit the name of your
+ existing Android Studio installation and append the version number. This way,
+ when you install the new version, it will not override the existing one.</li>
+ <li>Download the appropriate ZIP file for your operating system from the
+ <a href="http://tools.android.com/download/studio/canary/latest"
+ >canary channel download page</a>.
+ </li>
+ <li>Unzip the package and move the Android Studio 2.1 contents to the
+ appropriate location for applications on your system, then launch it.</li>
+ <li>Open the Settings dialog
+ (<strong>File > Settings</strong> on Windows/Linux, or
+ <strong>Android Studio > Preferences</strong> on Mac). In the left
+ panel, select <strong>Appearance & Behavior > System Settings >
+ Updates</strong>.
+ </li>
+ <li>On the Updates panel, select the <strong>Automatically
+ check updates for</strong> check box and select
+ <strong>Canary Channel</strong> from the drop-down list.
+ </li>
+</ol>
+
+<p>Keep this settings window open for the next step.</p>
+
+
+<h2 id="get-sdk">Get the Wear Preview SDK</h2>
+
+<p>To start developing with Wear Preview APIs, you need to install the
+Wear Preview SDK in Android Studio as follows:</p>
+
+<ol>
+ <li>While still viewing the Updates panel (step 4 from above),
+ select the <strong>Automatically
+ check updates for Android SDK</strong> check box and select
+ <strong>Preview Channel</strong> from the drop-down list.
+ </li>
+ <li>Click <strong>Check Now</strong>.</li>
+
+ <li>In the left panel, select <strong>Appearance & Behavior >
+ System Settings > Android SDK</strong>.
+
+ <li>Click the <strong>SDK Platforms</strong> tab, then select the
+ <strong>Wear Preview</strong> check box.</li>
+
+ <li>Click the <strong>SDK Tools</strong> tab, then select the
+ <strong>Android SDK Build Tools</strong>, <strong>Android SDK
+ Platform-Tools</strong>, and <strong>Android SDK Tools</strong> check
+ boxes.
+ </li>
+
+ <li>Click <strong>OK</strong>, then accept the licensing
+ agreements for any packages that need to be installed.
+ </li>
+</ol>
+
+
+<h2 id="create-update">Update or Create a Project</h2>
+
+<p>
+ To use the Wear Preview APIs, your project must be configured appropriately.
+</p>
+
+
+<h3 id="update">Update an existing project</h3>
+
+<p>Open the
+ <code>build.gradle</code> file for your module and update the values as
+ follows:
+</p>
+
+<pre>
+android {
+ compileSdkVersion <strong>'23'</strong>
+ buildToolsVersion <strong>'24.0.1-rc1'</strong>
+ ...
+
+ defaultConfig {
+ minSdkVersion <strong>'23'</strong>
+ targetSdkVersion <strong>'23'</strong>
+ ...
+ }
+ ...
+}</pre>
+
+
+<h3 id="create">Create a new project</h3>
+
+<p>To create a new project for development with the Wear Preview SDK:</p>
+
+<ol>
+ <li>Click <strong>File > New Project</strong>. and follow the steps until
+ you reach the Target Android Devices page.
+ </li>
+ <li>On this page, select <strong>Wear</strong> option.</li>
+ <li>Under <strong>Wear</strong> option, in the <strong>Minimum
+ SDK</strong> option list, select
+ <strong>API 23: Android API 6.0 (Wear Preview)</strong>.</li>
+</ol>
diff --git a/docs/html/wear/wear_toc.cs b/docs/html/wear/wear_toc.cs
index 65ac2e9..93f554f 100644
--- a/docs/html/wear/wear_toc.cs
+++ b/docs/html/wear/wear_toc.cs
@@ -1,74 +1,53 @@
<ul id="nav">
<li class="nav-section">
- <div class="nav-section-header empty"><a href="<?cs var:toroot ?>wear/preview/start.html">Get Started
- </a></div>
+ <div class="nav-section-header empty">
+ <a href="<?cs var:toroot ?>wear/preview/index.html">
+ Wear Developer Preview
+ </a></div>
</li>
<li class="nav-section">
- <div class="nav-section-header empty"><a href="<?cs var:toroot ?>wear/design/user-interface.html">UI Overview
- </a></div>
+ <div class="nav-section-header empty">
+ <a href="<?cs var:toroot ?>wear/preview/program.html">
+ Program Overview
+ </a></div>
</li>
<li class="nav-section">
- <div class="nav-section-header empty"><a href="<?cs var:toroot ?>wear/design/index.html">Design Principles
- </a></div>
+ <div class="nav-section-header">
+ <a href="<?cs var:toroot ?>wear/preview/api-overview.html">
+ API Overview
+ </a></div>
+
+ <ul>
+ <li><a href="<?cs var:toroot ?>wear/preview/features/wear-apk.html">
+ Wear APKs</a></li>
+ <li><a href="<?cs var:toroot ?>wear/preview/features/complications.html">
+ Complications</a></li>
+ </ul>
+
</li>
<li class="nav-section">
- <div class="nav-section-header empty"><a href="<?cs var:toroot ?>wear/notifications/creating.html">Creating Notifications for Android Wear
- </a></div>
+ <div class="nav-section-header empty">
+ <a href="<?cs var:toroot ?>wear/preview/downloads.html">
+ Downloads
+ </a></div>
</li>
<li class="nav-section">
- <div class="nav-section-header empty"><a href="<?cs var:toroot ?>wear/notifications/remote-input.html">Receiving Voice Input from a Notification
- </a></div>
+ <div class="nav-section-header empty">
+ <a href="<?cs var:toroot ?>wear/preview/start.html">
+ Get Started
+ </a></div>
</li>
<li class="nav-section">
- <div class="nav-section-header empty"><a href="<?cs var:toroot ?>wear/notifications/pages.html">Adding Pages to a Notification
- </a></div>
+ <div class="nav-section-header empty">
+ <a href="<?cs var:toroot ?>wear/preview/license.html">
+ License Agreement
+ </a></div>
</li>
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="<?cs var:toroot ?>wear/notifications/stacks.html">Stacking Notifications
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header"><a href="<?cs var:toroot ?>reference/android/preview/support/package-summary.html">Notification Reference</a></div>
- <ul class="tree-list-children">
-<li class="nav-section">
-<div class="nav-section-header-ref"><span class="tree-list-subtitle package" title="android.preview.support.v4.app">android.preview.support.v4.app</span></div>
- <ul>
-<li><a href="<?cs var:toroot ?>reference/android/preview/support/v4/app/NotificationManagerCompat.html">NotificationManagerCompat</a></li>
- </ul>
-</li>
-
-<li class="nav-section">
-<div class="nav-section-header-ref"><span class="tree-list-subtitle package" title="android.preview.support.wearable.notifications">android.preview.support.wearable.notifications</span></div>
-<ul>
-
-<li><a href="<?cs var:toroot ?>reference/android/preview/support/wearable/notifications/RemoteInput.html">RemoteInput</a></li>
-<li><a href="<?cs var:toroot ?>reference/android/preview/support/wearable/notifications/RemoteInput.Builder.html" >RemoteInput.Builder</a></li>
-
-<li><a href="<?cs var:toroot ?>reference/android/preview/support/wearable/notifications/WearableNotifications.html">WearableNotifications</a></li>
-
-<li><a href="<?cs var:toroot ?>reference/android/preview/support/wearable/notifications/WearableNotifications.Action.html">WearableNotifications.Action</a></li>
-
-<li><a href="<?cs var:toroot ?>reference/android/preview/support/wearable/notifications/WearableNotifications.Action.Builder.html">WearableNotifications.Action.Builder</a></li>
-
-<li><a href="<?cs var:toroot ?>reference/android/preview/support/wearable/notifications/WearableNotifications.Builder.html">WearableNotifications.Builder</a></li>
- </ul>
- </li>
-</ul>
-</li>
-
-
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="<?cs var:toroot ?>wear/license.html">License Agreement</a></div>
- </li>
-
-
</ul>
diff --git a/media/java/android/media/tv/TvInputService.java b/media/java/android/media/tv/TvInputService.java
index 168fcdc..210e62b 100644
--- a/media/java/android/media/tv/TvInputService.java
+++ b/media/java/android/media/tv/TvInputService.java
@@ -78,6 +78,8 @@
private static final boolean DEBUG = false;
private static final String TAG = "TvInputService";
+ private static final int DETACH_OVERLAY_VIEW_TIMEOUT_MS = 5000;
+
/**
* This is the interface name that a service implementing a TV input should say that it support
* -- that is, this is the action it uses for its intent filter. To be supported, the service
@@ -268,7 +270,6 @@
* Base class for derived classes to implement to provide a TV input session.
*/
public abstract static class Session implements KeyEvent.Callback {
- private static final int DETACH_OVERLAY_VIEW_TIMEOUT_MS = 5000;
private static final int POSITION_UPDATE_INTERVAL_MS = 1000;
private final KeyEvent.DispatcherState mDispatcherState = new KeyEvent.DispatcherState();
@@ -1256,7 +1257,7 @@
// Creates a container view to check hanging on the overlay view detaching.
// Adding/removing the overlay view to/from the container make the view attach/detach
// logic run on the main thread.
- mOverlayViewContainer = new FrameLayout(mContext);
+ mOverlayViewContainer = new FrameLayout(mContext.getApplicationContext());
mOverlayViewContainer.addView(mOverlayView);
// TvView's window type is TYPE_APPLICATION_MEDIA and we want to create
// an overlay window above the media window but below the application window.
@@ -1496,26 +1497,26 @@
POSITION_UPDATE_INTERVAL_MS);
}
}
+ }
- private final class OverlayViewCleanUpTask extends AsyncTask<View, Void, Void> {
- @Override
- protected Void doInBackground(View... views) {
- View overlayViewParent = views[0];
- try {
- Thread.sleep(DETACH_OVERLAY_VIEW_TIMEOUT_MS);
- } catch (InterruptedException e) {
- return null;
- }
- if (isCancelled()) {
- return null;
- }
- if (overlayViewParent.isAttachedToWindow()) {
- Log.e(TAG, "Time out on releasing overlay view. Killing "
- + overlayViewParent.getContext().getPackageName());
- Process.killProcess(Process.myPid());
- }
+ private static final class OverlayViewCleanUpTask extends AsyncTask<View, Void, Void> {
+ @Override
+ protected Void doInBackground(View... views) {
+ View overlayViewParent = views[0];
+ try {
+ Thread.sleep(DETACH_OVERLAY_VIEW_TIMEOUT_MS);
+ } catch (InterruptedException e) {
return null;
}
+ if (isCancelled()) {
+ return null;
+ }
+ if (overlayViewParent.isAttachedToWindow()) {
+ Log.e(TAG, "Time out on releasing overlay view. Killing "
+ + overlayViewParent.getContext().getPackageName());
+ Process.killProcess(Process.myPid());
+ }
+ return null;
}
}
diff --git a/packages/DocumentsUI/Android.mk b/packages/DocumentsUI/Android.mk
index 568e200..9d44a6d 100644
--- a/packages/DocumentsUI/Android.mk
+++ b/packages/DocumentsUI/Android.mk
@@ -36,7 +36,7 @@
# Only enable asserts on userdebug/eng builds
ifneq (,$(filter userdebug eng, $(TARGET_BUILD_VARIANT)))
-LOCAL_JACK_FLAGS += -D jack.assert.policy=enable
+LOCAL_JACK_FLAGS += -D jack.assert.policy=always
endif
LOCAL_PACKAGE_NAME := DocumentsUI
diff --git a/packages/MtpDocumentsProvider/Android.mk b/packages/MtpDocumentsProvider/Android.mk
index 0f945ee..c9e7195 100644
--- a/packages/MtpDocumentsProvider/Android.mk
+++ b/packages/MtpDocumentsProvider/Android.mk
@@ -11,7 +11,7 @@
# Only enable asserts on userdebug/eng builds
ifneq (,$(filter userdebug eng, $(TARGET_BUILD_VARIANT)))
-LOCAL_JACK_FLAGS += -D jack.assert.policy=enable
+LOCAL_JACK_FLAGS += -D jack.assert.policy=always
endif
include $(BUILD_PACKAGE)
diff --git a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
index 9aaddaa..6d6a4b5 100644
--- a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
+++ b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
@@ -646,7 +646,7 @@
if (DEBUG) Log.i(TAG, "Rebuilding...");
for (int i=0; i<apps.size(); i++) {
AppEntry entry = apps.get(i);
- if (filter == null || filter.filterApp(entry)) {
+ if (entry != null && (filter == null || filter.filterApp(entry))) {
synchronized (mEntriesMap) {
if (DEBUG_LOCKING) Log.v(TAG, "rebuild acquired lock");
if (comparator != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index eec2070..527d577 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -2184,9 +2184,8 @@
== View.VISIBLE;
boolean showOnKeyguard = shouldShowOnKeyguard(entry.notification);
if (suppressedSummary || (isLockscreenPublicMode() && !mShowLockscreenNotifications) ||
- (onKeyguard && (visibleNotifications >= maxNotifications
- && !childWithVisibleSummary
- || !showOnKeyguard))) {
+ (onKeyguard && !childWithVisibleSummary
+ && (visibleNotifications >= maxNotifications || !showOnKeyguard))) {
entry.row.setVisibility(View.GONE);
if (onKeyguard && showOnKeyguard && !childNotification && !suppressedSummary) {
mKeyguardIconOverflowContainer.getIconsView().addNotification(entry);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
index 34c9c0d..078b3c6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
@@ -374,10 +374,42 @@
mContentHeight = Math.max(Math.min(contentHeight, getHeight()), getMinHeight());;
mUnrestrictedContentHeight = Math.max(contentHeight, getMinHeight());
selectLayout(mAnimate /* animate */, false /* force */);
+
+ int minHeightHint = getMinContentHeightHint();
+
+ NotificationViewWrapper wrapper = getVisibleWrapper(mVisibleType);
+ if (wrapper != null) {
+ wrapper.setContentHeight(mContentHeight, minHeightHint);
+ }
+
+ wrapper = getVisibleWrapper(mTransformationStartVisibleType);
+ if (wrapper != null) {
+ wrapper.setContentHeight(mContentHeight, minHeightHint);
+ }
+
updateClipping();
invalidateOutline();
}
+ /**
+ * @return the minimum apparent height that the wrapper should allow for the purpose
+ * of aligning elements at the bottom edge. If this is larger than the content
+ * height, the notification is clipped instead of being further shrunk.
+ */
+ private int getMinContentHeightHint() {
+ if (mIsChildInGroup && (mVisibleType == VISIBLE_TYPE_SINGLELINE
+ || mTransformationStartVisibleType == VISIBLE_TYPE_SINGLELINE)) {
+ return mContext.getResources().getDimensionPixelSize(
+ com.android.internal.R.dimen.notification_action_list_height);
+ }
+ if (mHeadsUpChild != null) {
+ return mHeadsUpChild.getHeight();
+ } else {
+ return mContractedChild.getHeight() + mContext.getResources().getDimensionPixelSize(
+ com.android.internal.R.dimen.notification_action_list_height);
+ }
+ }
+
private void updateContentTransformation() {
int visibleType = calculateVisibleType();
if (visibleType != mVisibleType) {
@@ -493,11 +525,15 @@
} else {
int visibleType = calculateVisibleType();
if (visibleType != mVisibleType || force) {
- View visibleView = getViewForVisibleType(visibleType);
- if (visibleView != null) {
- visibleView.setVisibility(VISIBLE);
- transferRemoteInputFocus(visibleType);
- }
+ View visibleView = getViewForVisibleType(visibleType);
+ if (visibleView != null) {
+ visibleView.setVisibility(VISIBLE);
+ transferRemoteInputFocus(visibleType);
+ }
+ NotificationViewWrapper visibleWrapper = getVisibleWrapper(visibleType);
+ if (visibleWrapper != null) {
+ visibleWrapper.setContentHeight(mContentHeight, getMinContentHeightHint());
+ }
if (animate && ((visibleType == VISIBLE_TYPE_EXPANDED && mExpandedChild != null)
|| (visibleType == VISIBLE_TYPE_HEADSUP && mHeadsUpChild != null)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActionListTransformState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActionListTransformState.java
new file mode 100644
index 0000000..c0373be
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActionListTransformState.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2016 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.systemui.statusbar.notification;
+
+import android.text.Layout;
+import android.text.TextUtils;
+import android.util.Pools;
+import android.view.View;
+import android.widget.TextView;
+
+/**
+ * A transform state of the action list
+*/
+public class ActionListTransformState extends TransformState {
+
+ private static Pools.SimplePool<ActionListTransformState> sInstancePool
+ = new Pools.SimplePool<>(40);
+
+ @Override
+ protected boolean sameAs(TransformState otherState) {
+ return otherState instanceof ActionListTransformState;
+ }
+
+ public static ActionListTransformState obtain() {
+ ActionListTransformState instance = sInstancePool.acquire();
+ if (instance != null) {
+ return instance;
+ }
+ return new ActionListTransformState();
+ }
+
+ @Override
+ protected void resetTransformedView() {
+ // We need to keep the Y transformation, because this is used to keep the action list
+ // aligned at the bottom, unrelated to transforms.
+ float y = getTransformedView().getTranslationY();
+ super.resetTransformedView();
+ getTransformedView().setTranslationY(y);
+ }
+
+ @Override
+ public void recycle() {
+ super.recycle();
+ sInstancePool.release(this);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTemplateViewWrapper.java
index 889bd5c..7ca2df9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTemplateViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTemplateViewWrapper.java
@@ -41,6 +41,10 @@
private ProgressBar mProgressBar;
private TextView mTitle;
private TextView mText;
+ private View mActionsContainer;
+
+ private int mContentHeight;
+ private int mMinHeightHint;
protected NotificationTemplateViewWrapper(Context ctx, View view, ExpandableNotificationRow row) {
super(ctx, view, row);
@@ -123,6 +127,7 @@
// It's still a viewstub
mProgressBar = null;
}
+ mActionsContainer = mView.findViewById(com.android.internal.R.id.actions_container);
}
@Override
@@ -225,4 +230,21 @@
(int) (gSource * (1f - t) + gTarget * t),
(int) (bSource * (1f - t) + bTarget * t));
}
+
+ @Override
+ public void setContentHeight(int contentHeight, int minHeightHint) {
+ super.setContentHeight(contentHeight, minHeightHint);
+
+ mContentHeight = contentHeight;
+ mMinHeightHint = minHeightHint;
+ updateActionOffset();
+ }
+
+ private void updateActionOffset() {
+ if (mActionsContainer != null) {
+ // We should never push the actions higher than they are in the headsup view.
+ int constrainedContentHeight = Math.max(mContentHeight, mMinHeightHint);
+ mActionsContainer.setTranslationY(constrainedContentHeight - mView.getHeight());
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationViewWrapper.java
index 7a0df1f..22519e6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationViewWrapper.java
@@ -158,4 +158,7 @@
public void setShowingLegacyBackground(boolean showing) {
}
+
+ public void setContentHeight(int contentHeight, int minHeightHint) {
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/TransformState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/TransformState.java
index 8207215..4e643f0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/TransformState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/TransformState.java
@@ -374,6 +374,11 @@
result.initFrom(view);
return result;
}
+ if (view.getId() == com.android.internal.R.id.actions_container) {
+ ActionListTransformState result = ActionListTransformState.obtain();
+ result.initFrom(view);
+ return result;
+ }
if (view instanceof NotificationHeaderView) {
HeaderTransformState result = HeaderTransformState.obtain();
result.initFrom(view);
@@ -467,7 +472,7 @@
resetTransformedView();
}
- private void resetTransformedView() {
+ protected void resetTransformedView() {
mTransformedView.setTranslationX(0);
mTransformedView.setTranslationY(0);
mTransformedView.setScaleX(1.0f);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
index ee4a102..4ec36f6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
@@ -67,6 +67,9 @@
private SparseArray<ButtonDispatcher> mButtonDispatchers;
private String mCurrentLayout;
+ private View mLastRot0;
+ private View mLastRot90;
+
public NavigationBarInflaterView(Context context, AttributeSet attrs) {
super(context, attrs);
mDensity = context.getResources().getConfiguration().densityDpi;
@@ -163,6 +166,7 @@
String[] start = sets[0].split(BUTTON_SEPARATOR);
String[] center = sets[1].split(BUTTON_SEPARATOR);
String[] end = sets[2].split(BUTTON_SEPARATOR);
+ // Inflate these in start to end order or accessibility traversal will be messed up.
inflateButtons(start, (ViewGroup) mRot0.findViewById(R.id.ends_group), false);
inflateButtons(start, (ViewGroup) mRot90.findViewById(R.id.ends_group), true);
@@ -240,6 +244,15 @@
}
parent.addView(v);
addToDispatchers(v);
+ View lastView = landscape ? mLastRot90 : mLastRot0;
+ if (lastView != null) {
+ v.setAccessibilityTraversalAfter(lastView.getId());
+ }
+ if (landscape) {
+ mLastRot90 = v;
+ } else {
+ mLastRot0 = v;
+ }
return v;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index f4b7728..3c6e999 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -1544,6 +1544,9 @@
}
for (int i = 0; i < toRemove.size(); i++) {
removeNotification(toRemove.get(i).getStatusBarNotification().getKey(), ranking);
+ // we need to ensure that the view is actually properly removed from the viewstate
+ // as this won't happen anymore when kept in the parent.
+ mStackScroller.removeViewStateForView(toRemove.get(i));
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
index a855aed..095265a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
@@ -272,7 +272,7 @@
public boolean requestScrollTo() {
findScrollContainer();
- mScrollContainer.scrollTo(mScrollContainerChild);
+ mScrollContainer.lockScrollTo(mScrollContainerChild);
return true;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
index 662aedb..33b113a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -243,6 +243,7 @@
= new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
+ updateForcedScroll();
updateChildren();
mChildrenUpdateRequested = false;
getViewTreeObserver().removeOnPreDrawListener(this);
@@ -334,6 +335,7 @@
private boolean mDrawBackgroundAsSrc;
private boolean mFadedOut;
private boolean mGroupExpandedForMeasure;
+ private View mForcedScroll;
private float mBackgroundFadeAmount = 1.0f;
private static final Property<NotificationStackScrollLayout, Float> BACKGROUND_FADE =
new FloatProperty<NotificationStackScrollLayout>("backgroundFade") {
@@ -591,6 +593,23 @@
clampScrollPosition();
}
+ private void updateForcedScroll() {
+ if (mForcedScroll != null && (!mForcedScroll.hasFocus()
+ || !mForcedScroll.isAttachedToWindow())) {
+ mForcedScroll = null;
+ }
+ if (mForcedScroll != null) {
+ ExpandableView expandableView = (ExpandableView) mForcedScroll;
+ int positionInLinearLayout = getPositionInLinearLayout(expandableView);
+ int targetScroll = targetScrollForView(expandableView, positionInLinearLayout);
+
+ targetScroll = Math.max(0, Math.min(targetScroll, getScrollRange()));
+ if (mOwnScrollY < targetScroll || positionInLinearLayout < mOwnScrollY) {
+ mOwnScrollY = targetScroll;
+ }
+ }
+ }
+
private void requestChildrenUpdate() {
if (!mChildrenUpdateRequested) {
getViewTreeObserver().addOnPreDrawListener(mChildrenUpdater);
@@ -978,11 +997,19 @@
mScrollingEnabled = enable;
}
+ @Override
+ public void lockScrollTo(View v) {
+ if (mForcedScroll == v) {
+ return;
+ }
+ mForcedScroll = v;
+ scrollTo(v);
+ }
+
+ @Override
public boolean scrollTo(View v) {
ExpandableView expandableView = (ExpandableView) v;
- int positionInLinearLayout = getPositionInLinearLayout(v);
- int targetScroll = positionInLinearLayout + expandableView.getIntrinsicHeight() +
- getImeInset() - getHeight() + getTopPadding();
+ int targetScroll = targetScrollForView(expandableView, getPositionInLinearLayout(v));
if (mOwnScrollY < targetScroll) {
mScroller.startScroll(mScrollX, mOwnScrollY, 0, targetScroll - mOwnScrollY);
@@ -993,6 +1020,15 @@
return false;
}
+ /**
+ * @return the scroll necessary to make the bottom edge of {@param v} align with the top of
+ * the IME.
+ */
+ private int targetScrollForView(ExpandableView v, int positionInLinearLayout) {
+ return positionInLinearLayout + v.getIntrinsicHeight() +
+ getImeInset() - getHeight() + getTopPadding();
+ }
+
@Override
public WindowInsets onApplyWindowInsets(WindowInsets insets) {
mBottomInset = insets.getSystemWindowInsetBottom();
@@ -1111,6 +1147,7 @@
if (ev.getY() < mQsContainer.getBottom()) {
return false;
}
+ mForcedScroll = null;
initVelocityTrackerIfNotExists();
mVelocityTracker.addMovement(ev);
@@ -2787,6 +2824,14 @@
}
@Override
+ public void clearChildFocus(View child) {
+ super.clearChildFocus(child);
+ if (mForcedScroll == child) {
+ mForcedScroll = null;
+ }
+ }
+
+ @Override
public void requestDisallowLongPress() {
removeLongPressCallback();
}
@@ -2851,7 +2896,7 @@
private void clearTransientViews(ViewGroup viewGroup) {
while (viewGroup != null && viewGroup.getTransientViewCount() != 0) {
- viewGroup.removeTransientView(getTransientView(0));
+ viewGroup.removeTransientView(viewGroup.getTransientView(0));
}
}
@@ -3590,6 +3635,15 @@
}
/**
+ * Remove the a given view from the viewstate. This is currently used when the children are
+ * kept in the parent artificially to have a nicer animation.
+ * @param view the view to remove
+ */
+ public void removeViewStateForView(View view) {
+ mCurrentStackScrollState.removeViewStateForView(view);
+ }
+
+ /**
* A listener that is notified when some child locations might have changed.
*/
public interface OnChildLocationsChangedListener {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/ScrollContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/ScrollContainer.java
index 17b7871..b9d12ce 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/ScrollContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/ScrollContainer.java
@@ -36,6 +36,12 @@
boolean scrollTo(View v);
/**
+ * Like {@link #scrollTo(View)}, but keeps the scroll locked until the user
+ * scrolls, or {@param v} loses focus or is detached.
+ */
+ void lockScrollTo(View v);
+
+ /**
* Request that the view does not dismiss for the current touch.
*/
void requestDisallowDismiss();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
index f49067d..e8472ac 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
@@ -823,11 +823,6 @@
// The position for this child was never generated, let's continue.
continue;
}
- if (changingView.getVisibility() == View.GONE) {
- // The view was set to gone but the state never removed
- finalState.removeViewStateForView(changingView);
- continue;
- }
finalState.applyState(changingView, viewState);
mNewAddChildren.add(changingView);
diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto
index fd4c71e..c417fe8 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants.proto
@@ -2191,21 +2191,6 @@
// CATEGORY: SETTINGS
ACCOUNTS_WORK_PROFILE_SETTINGS = 401;
- // The number of packages optimized during the optimizing apps dialog.
- OPTIMIZING_APPS_NUM_PKGS_DEXOPTED = 402;
-
- // The number of packages which did not need optimizing during the optimizing apps dialog.
- OPTIMIZING_APPS_NUM_PKGS_SKIPPED = 403;
-
- // The number of packages which failed to optimize during the optimizing apps dialog.
- OPTIMIZING_APPS_NUM_PKGS_FAILED = 404;
-
- // The number of optimizable packages in the system.
- OPTIMIZING_APPS_NUM_PKGS_TOTAL = 405;
-
- // The total amount of time the user was blocked on the optimizing apps dialog.
- OPTIMIZING_APPS_TOTAL_TIME_MS = 406;
-
// Add new aosp constants above this line.
// END OF AOSP CONSTANTS
}
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index e1695e0..7f977dd 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -1737,7 +1737,7 @@
}
if (userState.mIsDisplayMagnificationEnabled ||
- userHasMagnificationServicesLocked(userState)) {
+ userHasListeningMagnificationServicesLocked(userState)) {
// Initialize the magnification controller if necessary
getMagnificationController();
mMagnificationController.register();
@@ -1761,6 +1761,22 @@
return false;
}
+ /**
+ * Returns whether the specified user has any services that are capable of
+ * controlling magnification and are actively listening for magnification updates.
+ */
+ private boolean userHasListeningMagnificationServicesLocked(UserState userState) {
+ final List<Service> services = userState.mBoundServices;
+ for (int i = 0, count = services.size(); i < count; i++) {
+ final Service service = services.get(i);
+ if (mSecurityPolicy.canControlMagnification(service)
+ && service.mInvocationHandler.mIsMagnificationCallbackEnabled) {
+ return true;
+ }
+ }
+ return false;
+ }
+
private void updateSoftKeyboardShowModeLocked(UserState userState) {
final int userId = userState.mUserId;
// Only check whether we need to reset the soft keyboard mode if it is not set to the
@@ -2864,19 +2880,28 @@
}
@Override
- public Region getMagnifiedRegion() {
+ public Region getMagnificationRegion() {
synchronized (mLock) {
- if (!isCalledForCurrentUserLocked()) {
- return Region.obtain();
- }
- }
- final long identity = Binder.clearCallingIdentity();
- try {
final Region region = Region.obtain();
- getMagnificationController().getMagnificationRegion(region);
- return region;
- } finally {
- Binder.restoreCallingIdentity(identity);
+ if (!isCalledForCurrentUserLocked()) {
+ return region;
+ }
+ MagnificationController magnificationController = getMagnificationController();
+ boolean forceRegistration = mSecurityPolicy.canControlMagnification(this);
+ boolean initiallyRegistered = magnificationController.isRegisteredLocked();
+ if (!initiallyRegistered && forceRegistration) {
+ magnificationController.register();
+ }
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ magnificationController.getMagnificationRegion(region);
+ return region;
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ if (!initiallyRegistered && forceRegistration) {
+ magnificationController.unregister();
+ }
+ }
}
}
@@ -2940,13 +2965,17 @@
if (!permissionGranted) {
return false;
}
- }
- final long identity = Binder.clearCallingIdentity();
- try {
- return getMagnificationController().setScaleAndCenter(
- scale, centerX, centerY, animate, mId);
- } finally {
- Binder.restoreCallingIdentity(identity);
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ MagnificationController magnificationController = getMagnificationController();
+ if (!magnificationController.isRegisteredLocked()) {
+ magnificationController.register();
+ }
+ return magnificationController
+ .setScaleAndCenter(scale, centerX, centerY, animate, mId);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
}
}
diff --git a/services/accessibility/java/com/android/server/accessibility/MagnificationController.java b/services/accessibility/java/com/android/server/accessibility/MagnificationController.java
index 027b6e2..7886b9e 100644
--- a/services/accessibility/java/com/android/server/accessibility/MagnificationController.java
+++ b/services/accessibility/java/com/android/server/accessibility/MagnificationController.java
@@ -151,6 +151,15 @@
}
}
+ /**
+ * Check if we are registered. Note that we may be planning to unregister at any moment.
+ *
+ * @return {@code true} if the controller is registered. {@code false} otherwise.
+ */
+ public boolean isRegisteredLocked() {
+ return mRegistered;
+ }
+
private void unregisterInternalLocked() {
if (mRegistered) {
mSpecAnimationBridge.setEnabled(false);
@@ -179,6 +188,10 @@
*/
private void onMagnificationRegionChanged(Region magnified, boolean updateSpec) {
synchronized (mLock) {
+ if (!mRegistered) {
+ // Don't update if we've unregistered
+ return;
+ }
boolean magnificationChanged = false;
boolean boundsChanged = false;
diff --git a/services/core/java/com/android/server/LockSettingsService.java b/services/core/java/com/android/server/LockSettingsService.java
index c2a1c50..5b6117d 100644
--- a/services/core/java/com/android/server/LockSettingsService.java
+++ b/services/core/java/com/android/server/LockSettingsService.java
@@ -340,8 +340,9 @@
}
public void onUnlockUser(int userId) {
- tieManagedProfileLockIfNecessary(userId, null);
+ // Hide notification first, as tie managed profile lock takes time
hideEncryptionNotification(new UserHandle(userId));
+ tieManagedProfileLockIfNecessary(userId, null);
// Now we have unlocked the parent user we should show notifications
// about any profiles that exist.
@@ -789,11 +790,10 @@
if (isSecure) {
tieManagedProfileLockIfNecessary(managedUserId, null);
} else {
- clearUserKeyProtection(managedUserId);
getGateKeeperService().clearSecureUserId(managedUserId);
mStorage.writePatternHash(null, managedUserId);
setKeystorePassword(null, managedUserId);
- fixateNewestUserKeyAuth(managedUserId);
+ clearUserKeyProtection(managedUserId);
mStorage.removeChildProfileLock(managedUserId);
removeKeystoreProfileKey(managedUserId);
}
@@ -828,11 +828,10 @@
byte[] currentHandle = getCurrentHandle(userId);
if (pattern == null) {
- clearUserKeyProtection(userId);
getGateKeeperService().clearSecureUserId(userId);
mStorage.writePatternHash(null, userId);
setKeystorePassword(null, userId);
- fixateNewestUserKeyAuth(userId);
+ clearUserKeyProtection(userId);
onUserLockChanged(userId);
return;
}
@@ -862,12 +861,8 @@
byte[] enrolledHandle = enrollCredential(currentHandle, savedCredential, pattern, userId);
if (enrolledHandle != null) {
- CredentialHash willStore
- = new CredentialHash(enrolledHandle, CredentialHash.VERSION_GATEKEEPER);
- setUserKeyProtection(userId, pattern,
- doVerifyPattern(pattern, willStore, true, 0, userId));
mStorage.writePatternHash(enrolledHandle, userId);
- fixateNewestUserKeyAuth(userId);
+ setUserKeyProtection(userId, pattern, verifyPattern(pattern, 0, userId));
onUserLockChanged(userId);
} else {
throw new RemoteException("Failed to enroll pattern");
@@ -890,11 +885,10 @@
throws RemoteException {
byte[] currentHandle = getCurrentHandle(userId);
if (password == null) {
- clearUserKeyProtection(userId);
getGateKeeperService().clearSecureUserId(userId);
mStorage.writePasswordHash(null, userId);
setKeystorePassword(null, userId);
- fixateNewestUserKeyAuth(userId);
+ clearUserKeyProtection(userId);
onUserLockChanged(userId);
return;
}
@@ -922,12 +916,8 @@
byte[] enrolledHandle = enrollCredential(currentHandle, savedCredential, password, userId);
if (enrolledHandle != null) {
- CredentialHash willStore
- = new CredentialHash(enrolledHandle, CredentialHash.VERSION_GATEKEEPER);
- setUserKeyProtection(userId, password,
- doVerifyPassword(password, willStore, true, 0, userId));
mStorage.writePasswordHash(enrolledHandle, userId);
- fixateNewestUserKeyAuth(userId);
+ setUserKeyProtection(userId, password, verifyPassword(password, 0, userId));
onUserLockChanged(userId);
} else {
throw new RemoteException("Failed to enroll password");
@@ -1032,11 +1022,11 @@
if (token == null) {
throw new RemoteException("Empty payload verifying a credential we just set");
}
- addUserKeyAuth(userId, token, secretFromCredential(credential));
+ changeUserKey(userId, token, secretFromCredential(credential));
}
private void clearUserKeyProtection(int userId) throws RemoteException {
- addUserKeyAuth(userId, null, null);
+ changeUserKey(userId, null, null);
}
private static byte[] secretFromCredential(String credential) throws RemoteException {
@@ -1055,23 +1045,18 @@
}
}
- private void addUserKeyAuth(int userId, byte[] token, byte[] secret)
+ private void changeUserKey(int userId, byte[] token, byte[] secret)
throws RemoteException {
final UserInfo userInfo = UserManager.get(mContext).getUserInfo(userId);
final IMountService mountService = getMountService();
final long callingId = Binder.clearCallingIdentity();
try {
- mountService.addUserKeyAuth(userId, userInfo.serialNumber, token, secret);
+ mountService.changeUserKey(userId, userInfo.serialNumber, token, null, secret);
} finally {
Binder.restoreCallingIdentity(callingId);
}
}
- private void fixateNewestUserKeyAuth(int userId)
- throws RemoteException {
- getMountService().fixateNewestUserKeyAuth(userId);
- }
-
@Override
public VerifyCredentialResponse checkPattern(String pattern, int userId) throws RemoteException {
return doVerifyPattern(pattern, false, 0, userId);
@@ -1087,11 +1072,6 @@
long challenge, int userId) throws RemoteException {
checkPasswordReadPermission(userId);
CredentialHash storedHash = mStorage.readPatternHash(userId);
- return doVerifyPattern(pattern, storedHash, hasChallenge, challenge, userId);
- }
-
- private VerifyCredentialResponse doVerifyPattern(String pattern, CredentialHash storedHash,
- boolean hasChallenge, long challenge, int userId) throws RemoteException {
boolean shouldReEnrollBaseZero = storedHash != null && storedHash.isBaseZeroPattern;
String patternToVerify;
@@ -1129,6 +1109,7 @@
}
return response;
+
}
@Override
@@ -1178,11 +1159,6 @@
long challenge, int userId) throws RemoteException {
checkPasswordReadPermission(userId);
CredentialHash storedHash = mStorage.readPasswordHash(userId);
- return doVerifyPassword(password, storedHash, hasChallenge, challenge, userId);
- }
-
- private VerifyCredentialResponse doVerifyPassword(String password, CredentialHash storedHash,
- boolean hasChallenge, long challenge, int userId) throws RemoteException {
return verifyCredential(userId, storedHash, password, hasChallenge, challenge,
new CredentialUtil() {
@Override
diff --git a/services/core/java/com/android/server/LockSettingsStorage.java b/services/core/java/com/android/server/LockSettingsStorage.java
index ab91a73..9ab6300 100644
--- a/services/core/java/com/android/server/LockSettingsStorage.java
+++ b/services/core/java/com/android/server/LockSettingsStorage.java
@@ -74,7 +74,7 @@
private SparseArray<Integer> mStoredCredentialType;
- static class CredentialHash {
+ class CredentialHash {
static final int TYPE_NONE = -1;
static final int TYPE_PATTERN = 1;
static final int TYPE_PASSWORD = 2;
diff --git a/services/core/java/com/android/server/MountService.java b/services/core/java/com/android/server/MountService.java
index c89b6ea..25ce485 100644
--- a/services/core/java/com/android/server/MountService.java
+++ b/services/core/java/com/android/server/MountService.java
@@ -2816,36 +2816,15 @@
}
}
- /*
- * Add this token/secret pair to the set of ways we can recover a disk encryption key.
- * Changing the token/secret for a disk encryption key is done in two phases: first, adding
- * a new token/secret pair with this call, then delting all other pairs with
- * fixateNewestUserKeyAuth. This allows other places where a credential is used, such as
- * Gatekeeper, to be updated between the two calls.
- */
@Override
- public void addUserKeyAuth(int userId, int serialNumber, byte[] token, byte[] secret) {
+ public void changeUserKey(int userId, int serialNumber,
+ byte[] token, byte[] oldSecret, byte[] newSecret) {
enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
waitForReady();
try {
- mCryptConnector.execute("cryptfs", "add_user_key_auth", userId, serialNumber,
- encodeBytes(token), encodeBytes(secret));
- } catch (NativeDaemonConnectorException e) {
- throw e.rethrowAsParcelableException();
- }
- }
-
- /*
- * Delete all disk encryption token/secret pairs except the most recently added one
- */
- @Override
- public void fixateNewestUserKeyAuth(int userId) {
- enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
- waitForReady();
-
- try {
- mCryptConnector.execute("cryptfs", "fixate_newest_user_key_auth", userId);
+ mCryptConnector.execute("cryptfs", "change_user_key", userId, serialNumber,
+ encodeBytes(token), encodeBytes(oldSecret), encodeBytes(newSecret));
} catch (NativeDaemonConnectorException e) {
throw e.rethrowAsParcelableException();
}
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index 98b3b08..a9a53a2 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -2237,8 +2237,13 @@
}
}
- new Session(accounts, response, account.type, expectActivityLaunch,
- false /* stripAuthTokenFromResult */, account.name,
+ new Session(
+ accounts,
+ response,
+ account.type,
+ expectActivityLaunch,
+ false /* stripAuthTokenFromResult */,
+ account.name,
false /* authDetailsRequired */) {
@Override
protected String toDebugString(long now) {
@@ -2310,6 +2315,15 @@
Intent intent = result.getParcelable(AccountManager.KEY_INTENT);
if (intent != null && notifyOnAuthFailure && !customTokens) {
+ /*
+ * Make sure that the supplied intent is owned by the authenticator
+ * giving it to the system. Otherwise a malicious authenticator could
+ * have users launching arbitrary activities by tricking users to
+ * interact with malicious notifications.
+ */
+ checkKeyIntent(
+ Binder.getCallingUid(),
+ intent);
doNotification(mAccounts,
account, result.getString(AccountManager.KEY_AUTH_FAILED_MESSAGE),
intent, accounts.userId);
diff --git a/services/core/java/com/android/server/am/ServiceRecord.java b/services/core/java/com/android/server/am/ServiceRecord.java
index bc297de..0a081e9 100644
--- a/services/core/java/com/android/server/am/ServiceRecord.java
+++ b/services/core/java/com/android/server/am/ServiceRecord.java
@@ -441,7 +441,7 @@
Notification localForegroundNoti = _foregroundNoti;
try {
if (localForegroundNoti.getSmallIcon() == null) {
- // It is not correct for the caller to supply a notification
+ // It is not correct for the caller to not supply a notification
// icon, but this used to be able to slip through, so for
// those dirty apps we will create a notification clearly
// blaming the app.
@@ -458,8 +458,8 @@
}
Context ctx = null;
try {
- ctx = ams.mContext.createPackageContext(
- appInfo.packageName, 0);
+ ctx = ams.mContext.createPackageContextAsUser(
+ appInfo.packageName, 0, new UserHandle(userId));
Notification.Builder notiBuilder = new Notification.Builder(ctx);
diff --git a/services/core/java/com/android/server/net/NetworkStatsObservers.java b/services/core/java/com/android/server/net/NetworkStatsObservers.java
index 6f781b3..230c2e9 100644
--- a/services/core/java/com/android/server/net/NetworkStatsObservers.java
+++ b/services/core/java/com/android/server/net/NetworkStatsObservers.java
@@ -81,8 +81,6 @@
*/
public DataUsageRequest register(DataUsageRequest inputRequest, Messenger messenger,
IBinder binder, int callingUid, @NetworkStatsAccess.Level int accessLevel) {
- checkVisibilityUids(callingUid, accessLevel, inputRequest.uids);
-
DataUsageRequest request = buildRequest(inputRequest);
RequestInfo requestInfo = buildRequestInfo(request, messenger, binder, callingUid,
accessLevel);
@@ -211,14 +209,13 @@
+ ". Overriding to a safer default of " + thresholdInBytes + " bytes");
}
return new DataUsageRequest(mNextDataUsageRequestId.incrementAndGet(),
- request.templates, request.uids, thresholdInBytes);
+ request.template, thresholdInBytes);
}
private RequestInfo buildRequestInfo(DataUsageRequest request,
Messenger messenger, IBinder binder, int callingUid,
@NetworkStatsAccess.Level int accessLevel) {
- if (accessLevel <= NetworkStatsAccess.Level.USER
- || request.uids != null && request.uids.length > 0) {
+ if (accessLevel <= NetworkStatsAccess.Level.USER) {
return new UserUsageRequestInfo(this, request, messenger, binder, callingUid,
accessLevel);
} else {
@@ -229,19 +226,6 @@
}
}
- private void checkVisibilityUids(int callingUid, @NetworkStatsAccess.Level int accessLevel,
- int[] uids) {
- if (uids == null) {
- return;
- }
- for (int i = 0; i < uids.length; i++) {
- if (!NetworkStatsAccess.isAccessibleToUser(uids[i], callingUid, accessLevel)) {
- throw new SecurityException("Caller " + callingUid + " cannot monitor network stats"
- + " for uid " + uids[i] + " with accessLevel " + accessLevel);
- }
- }
- }
-
/**
* Tracks information relevant to a data usage observer.
* It will notice when the calling process dies so we can self-expire.
@@ -359,15 +343,13 @@
@Override
protected boolean checkStats() {
- for (int i = 0; i < mRequest.templates.length; i++) {
- long bytesSoFar = getTotalBytesForNetwork(mRequest.templates[i]);
- if (LOGV) {
- Slog.v(TAG, bytesSoFar + " bytes so far since notification for "
- + mRequest.templates[i]);
- }
- if (bytesSoFar > mRequest.thresholdInBytes) {
- return true;
- }
+ long bytesSoFar = getTotalBytesForNetwork(mRequest.template);
+ if (LOGV) {
+ Slog.v(TAG, bytesSoFar + " bytes so far since notification for "
+ + mRequest.template);
+ }
+ if (bytesSoFar > mRequest.thresholdInBytes) {
+ return true;
}
return false;
}
@@ -405,20 +387,17 @@
@Override
protected boolean checkStats() {
- int[] uidsToMonitor = getUidsToMonitor();
+ int[] uidsToMonitor = mCollection.getRelevantUids(mAccessLevel, mCallingUid);
- for (int i = 0; i < mRequest.templates.length; i++) {
- for (int j = 0; j < uidsToMonitor.length; j++) {
- long bytesSoFar = getTotalBytesForNetworkUid(mRequest.templates[i],
- uidsToMonitor[j]);
+ for (int i = 0; i < uidsToMonitor.length; i++) {
+ long bytesSoFar = getTotalBytesForNetworkUid(mRequest.template, uidsToMonitor[i]);
- if (LOGV) {
- Slog.v(TAG, bytesSoFar + " bytes so far since notification for "
- + mRequest.templates[i] + " for uid=" + uidsToMonitor[j]);
- }
- if (bytesSoFar > mRequest.thresholdInBytes) {
- return true;
- }
+ if (LOGV) {
+ Slog.v(TAG, bytesSoFar + " bytes so far since notification for "
+ + mRequest.template + " for uid=" + uidsToMonitor[i]);
+ }
+ if (bytesSoFar > mRequest.thresholdInBytes) {
+ return true;
}
}
return false;
@@ -453,21 +432,6 @@
return 0;
}
}
-
- private int[] getUidsToMonitor() {
- if (mRequest.uids == null || mRequest.uids.length == 0) {
- return mCollection.getRelevantUids(mAccessLevel, mCallingUid);
- }
- // Pick only uids from the request that are currently accessible to the user
- IntArray accessibleUids = new IntArray(mRequest.uids.length);
- for (int i = 0; i < mRequest.uids.length; i++) {
- int uid = mRequest.uids[i];
- if (NetworkStatsAccess.isAccessibleToUser(uid, mCallingUid, mAccessLevel)) {
- accessibleUids.add(uid);
- }
- }
- return accessibleUids.toArray();
- }
}
private static class StatsContext {
diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java
index 2c2e9b9..8610fa1 100644
--- a/services/core/java/com/android/server/net/NetworkStatsService.java
+++ b/services/core/java/com/android/server/net/NetworkStatsService.java
@@ -578,9 +578,12 @@
if (tag == TAG_NONE) {
return getUidComplete().getHistory(template, uid, set, tag, fields, start, end,
accessLevel);
- } else {
+ } else if (uid == Binder.getCallingUid()) {
return getUidTagComplete().getHistory(template, uid, set, tag, fields,
start, end, accessLevel);
+ } else {
+ throw new SecurityException("Calling package " + mCallingPackage
+ + " cannot access tag information from a different uid");
}
}
@@ -761,12 +764,11 @@
}
@Override
- public DataUsageRequest registerDataUsageCallback(String callingPackage,
+ public DataUsageRequest registerUsageCallback(String callingPackage,
DataUsageRequest request, Messenger messenger, IBinder binder) {
checkNotNull(callingPackage, "calling package is null");
checkNotNull(request, "DataUsageRequest is null");
- checkNotNull(request.templates, "NetworkTemplate is null");
- checkArgument(request.templates.length > 0);
+ checkNotNull(request.template, "NetworkTemplate is null");
checkNotNull(messenger, "messenger is null");
checkNotNull(binder, "binder is null");
@@ -788,7 +790,7 @@
}
@Override
- public void unregisterDataUsageRequest(DataUsageRequest request) {
+ public void unregisterUsageRequest(DataUsageRequest request) {
checkNotNull(request, "DataUsageRequest is null");
int callingUid = Binder.getCallingUid();
diff --git a/services/core/java/com/android/server/pm/BackgroundDexOptService.java b/services/core/java/com/android/server/pm/BackgroundDexOptService.java
index 0a25402..ee02a99 100644
--- a/services/core/java/com/android/server/pm/BackgroundDexOptService.java
+++ b/services/core/java/com/android/server/pm/BackgroundDexOptService.java
@@ -144,11 +144,18 @@
if (DEBUG_DEXOPT) {
Log.i(TAG, "Updating package " + pkg);
}
+
// Update package if needed. Note that there can be no race between concurrent
// jobs because PackageDexOptimizer.performDexOpt is synchronized.
+
+ // checkProfiles is false to avoid merging profiles during boot which
+ // might interfere with background compilation (b/28612421).
+ // Unfortunately this will also means that "pm.dexopt.boot=speed-profile" will
+ // behave differently than "pm.dexopt.bg-dexopt=speed-profile" but that's a
+ // trade-off worth doing to save boot time work.
pm.performDexOpt(pkg,
/* instruction set */ null,
- /* checkProfiles */ true,
+ /* checkProfiles */ false,
PackageManagerService.REASON_BOOT,
/* force */ false);
}
diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
index f134e40..89747b5 100644
--- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java
+++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
@@ -28,6 +28,7 @@
import android.util.Slog;
import com.android.internal.os.InstallerConnection.InstallerException;
+import com.android.internal.util.IndentingPrintWriter;
import java.io.File;
import java.io.IOException;
@@ -122,6 +123,32 @@
return dexoptFlags;
}
+ /**
+ * Dumps the dexopt state of the given package {@code pkg} to the given {@code PrintWriter}.
+ */
+ void dumpDexoptState(IndentingPrintWriter pw, PackageParser.Package pkg) {
+ final String[] instructionSets = getAppDexInstructionSets(pkg.applicationInfo);
+ final String[] dexCodeInstructionSets = getDexCodeInstructionSets(instructionSets);
+
+ final List<String> paths = pkg.getAllCodePathsExcludingResourceOnly();
+
+ for (String instructionSet : dexCodeInstructionSets) {
+ pw.println("Instruction Set: " + instructionSet);
+ pw.increaseIndent();
+ for (String path : paths) {
+ String status = null;
+ try {
+ status = DexFile.getDexFileStatus(path, instructionSet);
+ } catch (IOException ioe) {
+ status = "[Exception]: " + ioe.getMessage();
+ }
+ pw.println("path: " + path);
+ pw.println("status: " + status);
+ }
+ pw.decreaseIndent();
+ }
+ }
+
private int performDexOptLI(PackageParser.Package pkg, String[] sharedLibraries,
String[] targetInstructionSets, boolean checkProfiles, String targetCompilerFilter) {
final String[] instructionSets = targetInstructionSets != null ?
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 4adfc3f..4e48e4d7 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -227,7 +227,6 @@
import com.android.internal.content.NativeLibraryHelper;
import com.android.internal.content.PackageHelper;
import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.internal.os.IParcelFileDescriptorFactory;
import com.android.internal.os.InstallerConnection.InstallerException;
import com.android.internal.os.SomeArgs;
@@ -4266,17 +4265,17 @@
synchronized (mPackages) {
final PackageParser.Package pkg = mPackages.get(packageName);
if (pkg == null) {
- throw new IllegalArgumentException("Unknown package: " + packageName);
+ return 0;
}
final BasePermission bp = mSettings.mPermissions.get(name);
if (bp == null) {
- throw new IllegalArgumentException("Unknown permission: " + name);
+ return 0;
}
SettingBase sb = (SettingBase) pkg.mExtras;
if (sb == null) {
- throw new IllegalArgumentException("Unknown package: " + packageName);
+ return 0;
}
PermissionsState permissionsState = sb.getPermissionsState();
@@ -7196,9 +7195,14 @@
}
}
+ // checkProfiles is false to avoid merging profiles during boot which
+ // might interfere with background compilation (b/28612421).
+ // Unfortunately this will also means that "pm.dexopt.boot=speed-profile" will
+ // behave differently than "pm.dexopt.bg-dexopt=speed-profile" but that's a
+ // trade-off worth doing to save boot time work.
int dexOptStatus = performDexOptTraced(pkg.packageName,
null /* instructionSet */,
- true /* checkProfiles */,
+ false /* checkProfiles */,
getCompilerFilterForReason(causeFirstBoot ? REASON_FIRST_BOOT : REASON_BOOT),
false /* force */);
switch (dexOptStatus) {
@@ -7217,17 +7221,16 @@
}
}
- final int elapsedTime = (int) TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startTime);
- MetricsLogger.action(mContext,
- MetricsEvent.OPTIMIZING_APPS_NUM_PKGS_DEXOPTED, numberOfPackagesOptimized);
- MetricsLogger.action(mContext,
- MetricsEvent.OPTIMIZING_APPS_NUM_PKGS_SKIPPED, numberOfPackagesSkipped);
- MetricsLogger.action(mContext,
- MetricsEvent.OPTIMIZING_APPS_NUM_PKGS_FAILED, numberOfPackagesFailed);
- MetricsLogger.action(mContext,
- MetricsEvent.OPTIMIZING_APPS_NUM_PKGS_TOTAL, getOptimizablePackages().size());
- MetricsLogger.action(mContext,
- MetricsEvent.OPTIMIZING_APPS_TOTAL_TIME_MS, elapsedTime);
+ final int elapsedTimeMs = (int) TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startTime);
+ // Report the elapsed time in deci-seconds (tenths of a second) rounded upwards
+ // (e.g. 1234 ms will become 13ds). This will help provide histograms at a more reasonable
+ // granularity.
+ final int elapsedTimeDs = ((elapsedTimeMs + 99) / 100);
+ MetricsLogger.histogram(mContext, "opt_dialog_num_dexopted", numberOfPackagesOptimized);
+ MetricsLogger.histogram(mContext, "opt_dialog_num_skipped", numberOfPackagesSkipped);
+ MetricsLogger.histogram(mContext, "opt_dialog_num_failed", numberOfPackagesFailed);
+ MetricsLogger.histogram(mContext, "opt_dialog_num_total", getOptimizablePackages().size());
+ MetricsLogger.histogram(mContext, "opt_dialog_time_decis", elapsedTimeDs);
}
@Override
@@ -15453,9 +15456,18 @@
removePackageLI(ps, (flags & REMOVE_CHATTY) != 0);
if ((flags & PackageManager.DELETE_KEEP_DATA) == 0) {
- destroyAppDataLIF(deletedPkg, UserHandle.USER_ALL,
+ final PackageParser.Package resolvedPkg;
+ if (deletedPkg != null) {
+ resolvedPkg = deletedPkg;
+ } else {
+ // We don't have a parsed package when it lives on an ejected
+ // adopted storage device, so fake something together
+ resolvedPkg = new PackageParser.Package(ps.name);
+ resolvedPkg.setVolumeUuid(ps.volumeUuid);
+ }
+ destroyAppDataLIF(resolvedPkg, UserHandle.USER_ALL,
StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE);
- destroyAppProfilesLIF(deletedPkg);
+ destroyAppProfilesLIF(resolvedPkg);
if (outInfo != null) {
outInfo.dataRemoved = true;
}
@@ -17773,6 +17785,7 @@
public static final int DUMP_INTENT_FILTER_VERIFIERS = 1 << 17;
public static final int DUMP_DOMAIN_PREFERRED = 1 << 18;
public static final int DUMP_FROZEN = 1 << 19;
+ public static final int DUMP_DEXOPT = 1 << 20;
public static final int OPTION_SHOW_FILTERS = 1 << 0;
@@ -17889,6 +17902,7 @@
pw.println(" write: write current settings now");
pw.println(" installs: details about install sessions");
pw.println(" check-permission <permission> <package> [<user>]: does pkg hold perm?");
+ pw.println(" dexopt: dump dexopt state");
pw.println(" <package.name>: info about given package");
return;
} else if ("--checkin".equals(opt)) {
@@ -18008,6 +18022,8 @@
dumpState.setDump(DumpState.DUMP_INSTALLS);
} else if ("frozen".equals(cmd)) {
dumpState.setDump(DumpState.DUMP_FROZEN);
+ } else if ("dexopt".equals(cmd)) {
+ dumpState.setDump(DumpState.DUMP_DEXOPT);
} else if ("write".equals(cmd)) {
synchronized (mPackages) {
mSettings.writeLPr();
@@ -18365,6 +18381,11 @@
ipw.decreaseIndent();
}
+ if (!checkin && dumpState.isDumping(DumpState.DUMP_DEXOPT)) {
+ if (dumpState.onTitlePrinted()) pw.println();
+ dumpDexoptStateLPr(pw, packageName);
+ }
+
if (!checkin && dumpState.isDumping(DumpState.DUMP_MESSAGES) && packageName == null) {
if (dumpState.onTitlePrinted()) pw.println();
mSettings.dumpReadMessagesLPr(pw, dumpState);
@@ -18403,6 +18424,32 @@
}
}
+ private void dumpDexoptStateLPr(PrintWriter pw, String packageName) {
+ final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ", 120);
+ ipw.println();
+ ipw.println("Dexopt state:");
+ ipw.increaseIndent();
+ Collection<PackageParser.Package> packages = null;
+ if (packageName != null) {
+ PackageParser.Package targetPackage = mPackages.get(packageName);
+ if (targetPackage != null) {
+ packages = Collections.singletonList(targetPackage);
+ } else {
+ ipw.println("Unable to find package: " + packageName);
+ return;
+ }
+ } else {
+ packages = mPackages.values();
+ }
+
+ for (PackageParser.Package pkg : packages) {
+ ipw.println("[" + pkg.packageName + "]");
+ ipw.increaseIndent();
+ mPackageDexOptimizer.dumpDexoptState(ipw, pkg);
+ ipw.decreaseIndent();
+ }
+ }
+
private String dumpDomainString(String packageName) {
List<IntentFilterVerificationInfo> iviList = getIntentFilterVerifications(packageName)
.getList();
@@ -19610,6 +19657,7 @@
final String label;
final int targetSdkVersion;
final PackageFreezer freezer;
+ final int[] installedUserIds;
// reader
synchronized (mPackages) {
@@ -19664,6 +19712,7 @@
label = String.valueOf(pm.getApplicationLabel(pkg.applicationInfo));
targetSdkVersion = pkg.applicationInfo.targetSdkVersion;
freezer = new PackageFreezer(packageName, "movePackageInternal");
+ installedUserIds = ps.queryInstalledUsers(sUserManager.getUserIds(), true);
}
final Bundle extras = new Bundle();
@@ -19701,10 +19750,12 @@
final PackageStats stats = new PackageStats(null, -1);
synchronized (mInstaller) {
- if (!getPackageSizeInfoLI(packageName, -1, stats)) {
- freezer.close();
- throw new PackageManagerException(MOVE_FAILED_INTERNAL_ERROR,
- "Failed to measure package size");
+ for (int userId : installedUserIds) {
+ if (!getPackageSizeInfoLI(packageName, userId, stats)) {
+ freezer.close();
+ throw new PackageManagerException(MOVE_FAILED_INTERNAL_ERROR,
+ "Failed to measure package size");
+ }
}
}
diff --git a/services/core/java/com/android/server/vr/VrManagerService.java b/services/core/java/com/android/server/vr/VrManagerService.java
index 844b5e6..48c0fee 100644
--- a/services/core/java/com/android/server/vr/VrManagerService.java
+++ b/services/core/java/com/android/server/vr/VrManagerService.java
@@ -16,6 +16,7 @@
package com.android.server.vr;
import android.Manifest;
+import android.app.ActivityManager;
import android.app.AppOpsManager;
import android.app.NotificationManager;
import android.annotation.NonNull;
@@ -47,6 +48,7 @@
import android.service.vr.VrListenerService;
import android.util.ArraySet;
import android.util.Slog;
+import android.util.SparseArray;
import com.android.internal.R;
import com.android.server.SystemConfig;
@@ -95,6 +97,7 @@
private static final int PENDING_STATE_DELAY_MS = 300;
private static final int EVENT_LOG_SIZE = 32;
+ private static final int INVALID_APPOPS_MODE = -1;
private static native void initializeNative();
private static native void setVrModeNative(boolean enabled);
@@ -114,12 +117,11 @@
private boolean mGuard;
private final RemoteCallbackList<IVrStateCallbacks> mRemoteCallbacks =
new RemoteCallbackList<>();
- private final ArraySet<String> mPreviousToggledListenerSettings = new ArraySet<>();
- private String mPreviousNotificationPolicyAccessPackage;
- private String mPreviousCoarseLocationPackage;
- private String mPreviousManageOverlayPackage;
+ private int mPreviousCoarseLocationMode = INVALID_APPOPS_MODE;
+ private int mPreviousManageOverlayMode = INVALID_APPOPS_MODE;
private VrState mPendingState;
private final ArrayDeque<VrState> mLoggingDeque = new ArrayDeque<>(EVENT_LOG_SIZE);
+ private final NotificationAccessManager mNotifAccessManager = new NotificationAccessManager();
private static final int MSG_VR_STATE_CHANGE = 0;
private static final int MSG_PENDING_VR_STATE_CHANGE = 1;
@@ -193,6 +195,39 @@
}
};
+ private final class NotificationAccessManager {
+ private final SparseArray<ArraySet<String>> mAllowedPackages = new SparseArray<>();
+
+ public void update(Collection<String> packageNames) {
+ int currentUserId = ActivityManager.getCurrentUser();
+
+ UserHandle currentUserHandle = new UserHandle(currentUserId);
+
+ ArraySet<String> allowed = mAllowedPackages.get(currentUserId);
+ if (allowed == null) {
+ allowed = new ArraySet<>();
+ }
+
+ for (String pkg : allowed) {
+ if (!packageNames.contains(pkg)) {
+ revokeNotificationListenerAccess(pkg);
+ revokeNotificationPolicyAccess(pkg);
+ }
+ }
+ for (String pkg : packageNames) {
+ if (!allowed.contains(pkg)) {
+ grantNotificationPolicyAccess(pkg);
+ grantNotificationListenerAccess(pkg, currentUserHandle);
+ }
+ }
+
+ allowed.clear();
+ allowed.addAll(packageNames);
+ mAllowedPackages.put(currentUserId, allowed);
+ }
+ }
+
+
/**
* Called when a user, package, or setting changes that could affect whether or not the
* currently bound VrListenerService is changed.
@@ -200,6 +235,20 @@
@Override
public void onEnabledComponentChanged() {
synchronized (mLock) {
+ int currentUser = ActivityManager.getCurrentUser();
+
+ // Update listeners
+ ArraySet<ComponentName> enabledListeners = mComponentObserver.getEnabled(currentUser);
+
+ ArraySet<String> enabledPackages = new ArraySet<>();
+ for (ComponentName n : enabledListeners) {
+ String pkg = n.getPackageName();
+ if (isDefaultAllowed(pkg)) {
+ enabledPackages.add(n.getPackageName());
+ }
+ }
+ mNotifAccessManager.update(enabledPackages);
+
if (mCurrentVrService == null) {
return; // No active services
}
@@ -616,21 +665,18 @@
} catch (NameNotFoundException e) {
}
- if (info == null) {
- Slog.e(TAG, "Couldn't set implied permissions for " + pName + ", no such package.");
+ if (info == null || !(info.isSystemApp() || info.isUpdatedSystemApp())) {
return;
}
- if (!(info.isSystemApp() || info.isUpdatedSystemApp())) {
- return; // Application is not pre-installed, avoid setting implied permissions
- }
-
mWasDefaultGranted = true;
-
- grantCoarseLocationAccess(pName, userId);
- grantOverlayAccess(pName, userId);
- grantNotificationPolicyAccess(pName);
- grantNotificationListenerAccess(pName, userId);
+ AppOpsManager mgr = mContext.getSystemService(AppOpsManager.class);
+ if (mgr == null) {
+ Slog.e(TAG, "No AppOpsManager, failed to set permissions for: " + pName);
+ return;
+ }
+ grantCoarseLocationAccess(mgr, pName, info.uid);
+ grantOverlayAccess(mgr, pName, info.uid);
}
/**
@@ -657,80 +703,89 @@
String pName = component.getPackageName();
if (mWasDefaultGranted) {
- revokeCoarseLocationAccess(userId);
- revokeOverlayAccess(userId);
- revokeNotificationPolicyAccess(pName);
- revokeNotificiationListenerAccess();
+ ApplicationInfo info = null;
+ try {
+ info = pm.getApplicationInfo(pName, PackageManager.GET_META_DATA);
+ } catch (NameNotFoundException e) {
+ }
+
+ if (info != null) {
+ AppOpsManager mgr = mContext.getSystemService(AppOpsManager.class);
+ if (mgr == null) {
+ Slog.e(TAG, "No AppOpsManager, failed to set permissions for: " + pName);
+ return;
+ }
+ revokeCoarseLocationAccess(mgr, pName, info.uid);
+ revokeOverlayAccess(mgr, pName, info.uid);
+ }
mWasDefaultGranted = false;
}
}
- private void grantCoarseLocationAccess(String pkg, UserHandle userId) {
+ private boolean isDefaultAllowed(String packageName) {
PackageManager pm = mContext.getPackageManager();
- boolean prev = (PackageManager.PERMISSION_GRANTED ==
- pm.checkPermission(android.Manifest.permission.ACCESS_COARSE_LOCATION, pkg));
- mPreviousCoarseLocationPackage = null;
- if (!prev) {
- pm.grantRuntimePermission(pkg, android.Manifest.permission.ACCESS_COARSE_LOCATION,
- userId);
- mPreviousCoarseLocationPackage = pkg;
+
+ ApplicationInfo info = null;
+ try {
+ info = pm.getApplicationInfo(packageName, PackageManager.GET_META_DATA);
+ } catch (NameNotFoundException e) {
+ }
+
+ if (info == null || !(info.isSystemApp() || info.isUpdatedSystemApp())) {
+ return false;
+ }
+ return true;
+ }
+
+ private void grantCoarseLocationAccess(AppOpsManager mgr, String packageName, int uid) {
+ mPreviousCoarseLocationMode = mgr.checkOpNoThrow(AppOpsManager.OP_COARSE_LOCATION, uid,
+ packageName);
+
+ if (mPreviousCoarseLocationMode != AppOpsManager.MODE_ALLOWED) {
+ mgr.setMode(AppOpsManager.OP_COARSE_LOCATION, uid, packageName,
+ AppOpsManager.MODE_ALLOWED);
}
}
- private void revokeCoarseLocationAccess(UserHandle userId) {
- PackageManager pm = mContext.getPackageManager();
- if (mPreviousCoarseLocationPackage != null) {
- pm.revokeRuntimePermission(mPreviousCoarseLocationPackage,
- android.Manifest.permission.ACCESS_COARSE_LOCATION, userId);
- mPreviousCoarseLocationPackage = null;
+ private void revokeCoarseLocationAccess(AppOpsManager mgr, String packageName, int uid) {
+ if (mPreviousCoarseLocationMode != AppOpsManager.MODE_ALLOWED) {
+ mgr.setMode(AppOpsManager.OP_COARSE_LOCATION, uid, packageName,
+ mPreviousCoarseLocationMode);
+ mPreviousCoarseLocationMode = INVALID_APPOPS_MODE;
}
}
- private void grantOverlayAccess(String pkg, UserHandle userId) {
- PackageManager pm = mContext.getPackageManager();
- boolean prev = (PackageManager.PERMISSION_GRANTED ==
- pm.checkPermission(android.Manifest.permission.SYSTEM_ALERT_WINDOW, pkg));
- mPreviousManageOverlayPackage = null;
- if (!prev) {
- pm.grantRuntimePermission(pkg, android.Manifest.permission.SYSTEM_ALERT_WINDOW,
- userId);
- mPreviousManageOverlayPackage = pkg;
+ private void grantOverlayAccess(AppOpsManager mgr, String packageName, int uid) {
+
+ mPreviousManageOverlayMode = mgr.checkOpNoThrow(AppOpsManager.OP_SYSTEM_ALERT_WINDOW, uid,
+ packageName);
+
+ if (mPreviousManageOverlayMode != AppOpsManager.MODE_ALLOWED) {
+ mgr.setMode(AppOpsManager.OP_SYSTEM_ALERT_WINDOW, uid, packageName,
+ AppOpsManager.MODE_ALLOWED);
}
}
- private void revokeOverlayAccess(UserHandle userId) {
- PackageManager pm = mContext.getPackageManager();
- if (mPreviousManageOverlayPackage != null) {
- pm.revokeRuntimePermission(mPreviousManageOverlayPackage,
- android.Manifest.permission.SYSTEM_ALERT_WINDOW, userId);
- mPreviousManageOverlayPackage = null;
+ private void revokeOverlayAccess(AppOpsManager mgr, String packageName, int uid) {
+ if (mPreviousManageOverlayMode != AppOpsManager.MODE_ALLOWED) {
+ mgr.setMode(AppOpsManager.OP_SYSTEM_ALERT_WINDOW, uid, packageName,
+ mPreviousManageOverlayMode);
+ mPreviousManageOverlayMode = INVALID_APPOPS_MODE;
}
}
private void grantNotificationPolicyAccess(String pkg) {
NotificationManager nm = mContext.getSystemService(NotificationManager.class);
- boolean prev = nm.isNotificationPolicyAccessGrantedForPackage(pkg);
- mPreviousNotificationPolicyAccessPackage = null;
- if (!prev) {
- mPreviousNotificationPolicyAccessPackage = pkg;
- nm.setNotificationPolicyAccessGranted(pkg, true);
- }
+ nm.setNotificationPolicyAccessGranted(pkg, true);
}
private void revokeNotificationPolicyAccess(String pkg) {
NotificationManager nm = mContext.getSystemService(NotificationManager.class);
- if (mPreviousNotificationPolicyAccessPackage != null) {
- if (mPreviousNotificationPolicyAccessPackage.equals(pkg)) {
- // Remove any DND zen rules possibly created by the package.
- nm.removeAutomaticZenRules(mPreviousNotificationPolicyAccessPackage);
- // Remove Notification Policy Access.
- nm.setNotificationPolicyAccessGranted(mPreviousNotificationPolicyAccessPackage, false);
- mPreviousNotificationPolicyAccessPackage = null;
- } else {
- Slog.e(TAG, "Couldn't remove Notification Policy Access for package: " + pkg);
- }
- }
+ // Remove any DND zen rules possibly created by the package.
+ nm.removeAutomaticZenRules(pkg);
+ // Remove Notification Policy Access.
+ nm.setNotificationPolicyAccessGranted(pkg, false);
}
private void grantNotificationListenerAccess(String pkg, UserHandle userId) {
@@ -742,13 +797,10 @@
ArraySet<String> current = getCurrentNotifListeners(resolver);
- mPreviousToggledListenerSettings.clear();
-
for (ComponentName c : possibleServices) {
String flatName = c.flattenToString();
if (Objects.equals(c.getPackageName(), pkg)
&& !current.contains(flatName)) {
- mPreviousToggledListenerSettings.add(flatName);
current.add(flatName);
}
}
@@ -760,20 +812,25 @@
}
}
- private void revokeNotificiationListenerAccess() {
- if (mPreviousToggledListenerSettings.isEmpty()) {
- return;
- }
-
+ private void revokeNotificationListenerAccess(String pkg) {
ContentResolver resolver = mContext.getContentResolver();
ArraySet<String> current = getCurrentNotifListeners(resolver);
- current.removeAll(mPreviousToggledListenerSettings);
- mPreviousToggledListenerSettings.clear();
+ ArrayList<String> toRemove = new ArrayList<>();
+
+ for (String c : current) {
+ ComponentName component = ComponentName.unflattenFromString(c);
+ if (component.getPackageName().equals(pkg)) {
+ toRemove.add(c);
+ }
+ }
+
+ current.removeAll(toRemove);
String flatSettings = formatSettings(current);
Settings.Secure.putString(resolver, Settings.Secure.ENABLED_NOTIFICATION_LISTENERS,
flatSettings);
+
}
private ArraySet<String> getCurrentNotifListeners(ContentResolver resolver) {
diff --git a/services/core/java/com/android/server/wm/AppWindowAnimator.java b/services/core/java/com/android/server/wm/AppWindowAnimator.java
index 49dab0a..a37b65a 100644
--- a/services/core/java/com/android/server/wm/AppWindowAnimator.java
+++ b/services/core/java/com/android/server/wm/AppWindowAnimator.java
@@ -185,8 +185,7 @@
clearThumbnail();
setNullAnimation();
if (mAppToken.deferClearAllDrawn) {
- mAppToken.allDrawn = false;
- mAppToken.deferClearAllDrawn = false;
+ mAppToken.clearAllDrawn();
}
mStackClip = STACK_CLIP_BEFORE_ANIM;
}
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 805c986..a234241 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -27,6 +27,7 @@
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
import static com.android.server.wm.WindowManagerService.WINDOW_REPLACEMENT_TIMEOUT_DURATION;
+import static com.android.server.wm.WindowManagerService.H.NOTIFY_ACTIVITY_DRAWN;
import com.android.server.input.InputApplicationHandle;
import com.android.server.wm.WindowManagerService.H;
@@ -65,10 +66,6 @@
final boolean voiceInteraction;
- // Whether we're performing an entering animation with a saved surface.
- boolean mAnimatingWithSavedSurface;
-
-
Task mTask;
boolean appFullscreen;
int requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
@@ -160,6 +157,13 @@
}
}
+ void setVisibleBeforeClientHidden() {
+ for (int i = allAppWindows.size() - 1; i >= 0; i--) {
+ final WindowState w = allAppWindows.get(i);
+ w.setVisibleBeforeClientHidden();
+ }
+ }
+
void onFirstWindowDrawn(WindowState win, WindowStateAnimator winAnimator) {
firstWindowDrawn = true;
@@ -295,7 +299,7 @@
// If we're animating with a saved surface, we're already visible.
// Return true so that the alpha doesn't get cleared.
if (!win.mAppFreezing
- && (win.mViewVisibility == View.VISIBLE || mAnimatingWithSavedSurface
+ && (win.mViewVisibility == View.VISIBLE || win.isAnimatingWithSavedSurface()
|| (win.mWinAnimator.isAnimationSet()
&& !service.mAppTransition.isTransitionSet()))
&& !win.mDestroying
@@ -329,11 +333,14 @@
final DisplayContentList displayList = new DisplayContentList();
for (int i = allWindows.size() - 1; i >= 0; i--) {
final WindowState win = allWindows.get(i);
- if (!win.mDestroying) {
+
+ if (!(mAppStopped || win.mWindowRemovalAllowed)) {
continue;
}
- if (!(mAppStopped || win.mWindowRemovalAllowed)) {
+ win.mWinAnimator.destroyPreservedSurfaceLocked();
+
+ if (!win.mDestroying) {
continue;
}
@@ -344,7 +351,6 @@
win.destroyOrSaveSurface();
if (win.mRemoveOnExit) {
- win.mAnimatingExit = false;
service.removeWindowInnerLocked(win);
}
final DisplayContent displayContent = win.getDisplayContent();
@@ -388,43 +394,56 @@
return allDrawn;
}
- boolean hasSavedSurface() {
+ boolean canRestoreSurfaces() {
for (int i = allAppWindows.size() -1; i >= 0; i--) {
- final WindowState ws = allAppWindows.get(i);
- if (ws.hasSavedSurface()) {
+ final WindowState w = allAppWindows.get(i);
+ if (w.canRestoreSurface()) {
return true;
}
}
return false;
}
+ void clearVisibleBeforeClientHidden() {
+ for (int i = allAppWindows.size() - 1; i >= 0; i--) {
+ final WindowState w = allAppWindows.get(i);
+ w.clearVisibleBeforeClientHidden();
+ }
+ }
+
void restoreSavedSurfaces() {
- if (!hasSavedSurface()) {
+ if (!canRestoreSurfaces()) {
+ clearVisibleBeforeClientHidden();
return;
}
- mAnimatingWithSavedSurface = true;
-
// Check if we have enough drawn windows to mark allDrawn= true.
int numInteresting = 0;
int numDrawn = 0;
for (int i = allAppWindows.size() - 1; i >= 0; i--) {
WindowState w = allAppWindows.get(i);
- if (w.hasSavedSurface()) {
- w.restoreSavedSurface();
- }
- if (w != startingWindow && !w.mAppDied
+ if (w != startingWindow && !w.mAppDied && w.wasVisibleBeforeClientHidden()
&& (!mAppAnimator.freezingScreen || !w.mAppFreezing)) {
numInteresting++;
+ if (w.hasSavedSurface()) {
+ w.restoreSavedSurface();
+ }
if (w.isDrawnLw()) {
numDrawn++;
}
}
}
- allDrawn |= (numInteresting > 0) && (numInteresting == numDrawn);
+ if (!allDrawn) {
+ allDrawn = (numInteresting > 0) && (numInteresting == numDrawn);
+ if (allDrawn) {
+ service.mH.obtainMessage(NOTIFY_ACTIVITY_DRAWN, token).sendToTarget();
+ }
+ }
+ clearVisibleBeforeClientHidden();
if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.d(TAG,
- "restoreSavedSurfaces: " + appWindowToken + " allDrawn=" + allDrawn);
+ "restoreSavedSurfaces: " + appWindowToken + " allDrawn=" + allDrawn
+ + " numInteresting=" + numInteresting + " numDrawn=" + numDrawn);
}
void destroySavedSurfaces() {
@@ -432,7 +451,11 @@
WindowState win = allAppWindows.get(i);
win.destroySavedSurface();
}
- mAnimatingWithSavedSurface = false;
+ }
+
+ void clearAllDrawn() {
+ allDrawn = false;
+ deferClearAllDrawn = false;
}
@Override
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 1fdc714..fba439f 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -378,6 +378,8 @@
* We save the focused task region once we find it, and add it back at the end.
*/
+ task.getDimBounds(mTmpRect);
+
if (task == focusedTask) {
addBackFocusedTask = true;
mTmpRect2.set(mTmpRect);
@@ -385,7 +387,6 @@
final boolean isFreeformed = task.inFreeformWorkspace();
if (task != focusedTask || isFreeformed) {
- task.getDimBounds(mTmpRect);
if (isFreeformed) {
// If the task is freeformed, enlarge the area to account for outside
// touch area for resize.
diff --git a/services/core/java/com/android/server/wm/DockedStackDividerController.java b/services/core/java/com/android/server/wm/DockedStackDividerController.java
index ca68d55..6142511 100644
--- a/services/core/java/com/android/server/wm/DockedStackDividerController.java
+++ b/services/core/java/com/android/server/wm/DockedStackDividerController.java
@@ -377,6 +377,10 @@
checkMinimizeChanged(true /* animate */);
}
+ boolean isMinimizedDock() {
+ return mMinimizedDock;
+ }
+
private void checkMinimizeChanged(boolean animate) {
if (mDisplayContent.getDockedStackVisibleForUserLocked() == null) {
return;
diff --git a/services/core/java/com/android/server/wm/WindowManagerDebugConfig.java b/services/core/java/com/android/server/wm/WindowManagerDebugConfig.java
index 5d3cc16..f11281e 100644
--- a/services/core/java/com/android/server/wm/WindowManagerDebugConfig.java
+++ b/services/core/java/com/android/server/wm/WindowManagerDebugConfig.java
@@ -75,5 +75,5 @@
static final boolean DEBUG_WINDOW_CROP = false;
static final String TAG_KEEP_SCREEN_ON = "DebugKeepScreenOn";
- static final boolean DEBUG_KEEP_SCREEN_ON = true;
+ static final boolean DEBUG_KEEP_SCREEN_ON = false;
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index be888fe..a0b8c35 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -2170,7 +2170,7 @@
* Returns true if we're done setting up any transitions.
*/
private boolean prepareWindowReplacementTransition(AppWindowToken atoken) {
- atoken.allDrawn = false;
+ atoken.clearAllDrawn();
WindowState replacedWindow = null;
for (int i = atoken.windows.size() - 1; i >= 0 && replacedWindow == null; i--) {
WindowState candidate = atoken.windows.get(i);
@@ -2316,7 +2316,7 @@
if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "Preserving " + win + " until the new one is "
+ "added");
// TODO: We are overloading mAnimatingExit flag to prevent the window state from
- // been removed. We probably need another falg to indicate that window removal
+ // been removed. We probably need another flag to indicate that window removal
// should be deffered vs. overloading the flag that says we are playing an exit
// animation.
win.mAnimatingExit = true;
@@ -2464,7 +2464,7 @@
mTokenMap.remove(token.token);
} else if (atoken != null) {
atoken.firstWindowDrawn = false;
- atoken.allDrawn = false;
+ atoken.clearAllDrawn();
}
}
@@ -4423,6 +4423,7 @@
// Now that the app is going invisible, we can remove it. It will be restarted
// if made visible again.
wtoken.removeAllDeadWindows();
+ wtoken.setVisibleBeforeClientHidden();
} else if (visible) {
if (!mAppTransition.isTransitionSet() && mAppTransition.isReady()) {
// Add the app mOpeningApps if transition is unset but ready. This means
@@ -4434,8 +4435,7 @@
// If the token is currently hidden (should be the common case), or has been
// stopped, then we need to set up to wait for its windows to be ready.
if (wtoken.hidden || wtoken.mAppStopped) {
- wtoken.allDrawn = false;
- wtoken.deferClearAllDrawn = false;
+ wtoken.clearAllDrawn();
// If the app was already visible, don't reset the waitingToShow state.
if (wtoken.hidden) {
@@ -7534,6 +7534,7 @@
imeTargetStack.getDockSide() : DOCKED_INVALID;
final boolean imeOnTop = (imeDockSide == DOCKED_TOP);
final boolean imeOnBottom = (imeDockSide == DOCKED_BOTTOM);
+ final boolean dockMinimized = displayContent.mDividerControllerLocked.isMinimizedDock();
// The divider could be adjusted for IME position, or be thinner than usual,
// or both. There are three possible cases:
@@ -7541,7 +7542,7 @@
// - If IME is visible, and focus is on bottom, divider is moved for IME and thinner.
// - If IME is not visible, divider is not moved and is normal width.
- if (imeVisible && dockVisible && (imeOnTop || imeOnBottom)) {
+ if (imeVisible && dockVisible && (imeOnTop || imeOnBottom) && !dockMinimized) {
final ArrayList<TaskStack> stacks = displayContent.getStacks();
for (int i = stacks.size() - 1; i >= 0; --i) {
final TaskStack stack = stacks.get(i);
@@ -9233,8 +9234,7 @@
}
winAnimator.mDrawState = DRAW_PENDING;
if (w.mAppToken != null) {
- w.mAppToken.allDrawn = false;
- w.mAppToken.deferClearAllDrawn = false;
+ w.mAppToken.clearAllDrawn();
}
}
if (!mResizingWindows.contains(w)) {
@@ -9391,7 +9391,7 @@
Slog.w(TAG_WM, "LEAKED SURFACE (app token hidden): "
+ ws + " surface=" + wsa.mSurfaceController
+ " token=" + ws.mAppToken
- + " saved=" + ws.mAppToken.hasSavedSurface());
+ + " saved=" + ws.hasSavedSurface());
if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", false);
wsa.destroySurface();
leakedSurface = true;
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 7341e1e..b66de89 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -435,7 +435,15 @@
// Whether the window has a saved surface from last pause, which can be
// used to start an entering animation earlier.
- public boolean mSurfaceSaved = false;
+ private boolean mSurfaceSaved = false;
+
+ // Whether we're performing an entering animation with a saved surface.
+ private boolean mAnimatingWithSavedSurface;
+
+ // Whether the window was visible when we set the app to invisible last time. WM uses
+ // this as a hint to restore the surface (if available) for early animation next time
+ // the app is brought visible.
+ boolean mWasVisibleBeforeClientHidden;
// This window will be replaced due to relaunch. This allows window manager
// to differentiate between simple removal of a window and replacement. In the latter case it
@@ -697,7 +705,7 @@
// The offset from the layout containing frame to the actual containing frame.
final int layoutXDiff;
final int layoutYDiff;
- if (mInsetFrame.isEmpty() && (fullscreenTask || layoutInParentFrame())) {
+ if (fullscreenTask || layoutInParentFrame()) {
// We use the parent frame as the containing frame for fullscreen and child windows
mContainingFrame.set(pf);
mDisplayFrame.set(df);
@@ -1586,11 +1594,12 @@
win.transferDimToReplacement();
}
win.mWillReplaceWindow = false;
+ final boolean animateReplacingWindow = win.mAnimateReplacingWindow;
win.mAnimateReplacingWindow = false;
win.mReplacingRemoveRequested = false;
win.mReplacingWindow = null;
mSkipEnterAnimationForSeamlessReplacement = false;
- if (win.mAnimatingExit) {
+ if (win.mAnimatingExit || !animateReplacingWindow) {
mService.removeWindowInnerLocked(win);
}
}
@@ -1948,7 +1957,20 @@
}
boolean isAnimatingWithSavedSurface() {
- return mAppToken != null && mAppToken.mAnimatingWithSavedSurface;
+ return mAnimatingWithSavedSurface;
+ }
+
+ public void setVisibleBeforeClientHidden() {
+ mWasVisibleBeforeClientHidden |=
+ (mViewVisibility == View.VISIBLE || mAnimatingWithSavedSurface);
+ }
+
+ public void clearVisibleBeforeClientHidden() {
+ mWasVisibleBeforeClientHidden = false;
+ }
+
+ public boolean wasVisibleBeforeClientHidden() {
+ return mWasVisibleBeforeClientHidden;
}
private boolean shouldSaveSurface() {
@@ -1957,6 +1979,10 @@
return false;
}
+ if (!mWasVisibleBeforeClientHidden) {
+ return false;
+ }
+
if ((mAttrs.flags & FLAG_SECURE) != 0) {
// We don't save secure surfaces since their content shouldn't be shown while the app
// isn't on screen and content might leak through during the transition animation with
@@ -2019,18 +2045,22 @@
} else {
mWinAnimator.destroySurfaceLocked();
}
+ // Clear animating flags now, since the surface is now gone. (Note this is true even
+ // if the surface is saved, to outside world the surface is still NO_SURFACE.)
+ mAnimatingExit = false;
}
- public void destroySavedSurface() {
+ void destroySavedSurface() {
if (mSurfaceSaved) {
if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) {
Slog.v(TAG, "Destroying saved surface: " + this);
}
mWinAnimator.destroySurfaceLocked();
}
+ mWasVisibleBeforeClientHidden = false;
}
- public void restoreSavedSurface() {
+ void restoreSavedSurface() {
if (!mSurfaceSaved) {
return;
}
@@ -2038,6 +2068,7 @@
if (mWinAnimator.mSurfaceController != null) {
setHasSurface(true);
mWinAnimator.mDrawState = WindowStateAnimator.READY_TO_SHOW;
+ mAnimatingWithSavedSurface = true;
if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) {
Slog.v(TAG, "Restoring saved surface: " + this);
@@ -2050,10 +2081,30 @@
}
}
- public boolean hasSavedSurface() {
+ boolean canRestoreSurface() {
+ return mWasVisibleBeforeClientHidden && mSurfaceSaved;
+ }
+
+ boolean hasSavedSurface() {
return mSurfaceSaved;
}
+ void clearHasSavedSurface() {
+ mSurfaceSaved = false;
+ mAnimatingWithSavedSurface = false;
+ mWasVisibleBeforeClientHidden = false;
+ }
+
+ void clearAnimatingWithSavedSurface() {
+ if (mAnimatingWithSavedSurface) {
+ // App has drawn something to its windows, we're no longer animating with
+ // the saved surfaces.
+ if (DEBUG_ANIM) Slog.d(TAG,
+ "clearAnimatingWithSavedSurface(): win=" + this);
+ mAnimatingWithSavedSurface = false;
+ }
+ }
+
@Override
public boolean isDefaultDisplay() {
final DisplayContent displayContent = getDisplayContent();
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index e5f603c..f0bba4a 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -584,14 +584,8 @@
+ drawStateToString());
}
- if (mWin.mAppToken != null && mWin.mAppToken.mAnimatingWithSavedSurface) {
- // App has drawn something to its windows, we're no longer animating with
- // the saved surfaces. If the user exits now, we only want to save again
- // if allDrawn is true.
- if (DEBUG_ANIM) Slog.d(TAG,
- "finishDrawingLocked: mAnimatingWithSavedSurface=false " + mWin);
- mWin.mAppToken.mAnimatingWithSavedSurface = false;
- }
+ mWin.clearAnimatingWithSavedSurface();
+
if (mDrawState == DRAW_PENDING) {
if (DEBUG_SURFACE_TRACE || DEBUG_ANIM || SHOW_TRANSACTIONS || DEBUG_ORIENTATION)
Slog.v(TAG, "finishDrawingLocked: mDrawState=COMMIT_DRAW_PENDING " + mWin + " in "
@@ -659,6 +653,13 @@
mDestroyPreservedSurfaceUponRedraw = false;
}
+ void markPreservedSurfaceForDestroy() {
+ if (mDestroyPreservedSurfaceUponRedraw
+ && !mService.mDestroyPreservedSurface.contains(mWin)) {
+ mService.mDestroyPreservedSurface.add(mWin);
+ }
+ }
+
WindowSurfaceController createSurfaceLocked() {
final WindowState w = mWin;
if (w.hasSavedSurface()) {
@@ -680,8 +681,7 @@
mDrawState = DRAW_PENDING;
if (w.mAppToken != null) {
if (w.mAppToken.mAppAnimator.animation == null) {
- w.mAppToken.allDrawn = false;
- w.mAppToken.deferClearAllDrawn = false;
+ w.mAppToken.clearAllDrawn();
} else {
// Currently animating, persist current state of allDrawn until animation
// is complete.
@@ -833,20 +833,19 @@
}
boolean hasSurface() {
- return !mWin.mSurfaceSaved
+ return !mWin.hasSavedSurface()
&& mSurfaceController != null && mSurfaceController.hasSurface();
}
void destroySurfaceLocked() {
final AppWindowToken wtoken = mWin.mAppToken;
if (wtoken != null) {
- wtoken.mAnimatingWithSavedSurface = false;
if (mWin == wtoken.startingWindow) {
wtoken.startingDisplayed = false;
}
}
- mWin.mSurfaceSaved = false;
+ mWin.clearHasSavedSurface();
if (mSurfaceController == null) {
return;
@@ -1518,9 +1517,7 @@
if (prepared && mLastHidden && mDrawState == HAS_DRAWN) {
if (showSurfaceRobustlyLocked()) {
- if (mDestroyPreservedSurfaceUponRedraw) {
- mService.mDestroyPreservedSurface.add(mWin);
- }
+ markPreservedSurfaceForDestroy();
mAnimator.requestRemovalOfReplacedWindows(w);
mLastHidden = false;
if (mIsWallpaper) {
diff --git a/services/tests/servicestests/src/com/android/server/net/NetworkStatsObserversTest.java b/services/tests/servicestests/src/com/android/server/net/NetworkStatsObserversTest.java
index cff5876..21560ac 100644
--- a/services/tests/servicestests/src/com/android/server/net/NetworkStatsObserversTest.java
+++ b/services/tests/servicestests/src/com/android/server/net/NetworkStatsObserversTest.java
@@ -56,7 +56,7 @@
import com.android.server.net.NetworkStatsServiceTest.LatchedHandler;
import java.util.ArrayList;
-import java.util.Arrays;
+import java.util.Objects;
import java.util.List;
import junit.framework.TestCase;
@@ -91,7 +91,6 @@
private static final long BASE_BYTES = 7 * MB_IN_BYTES;
private static final int INVALID_TYPE = -1;
- private static final int[] NO_UIDS = null;
private static final VpnInfo[] VPN_INFO = new VpnInfo[0];
private long mElapsedRealtime;
@@ -134,112 +133,60 @@
public void testRegister_thresholdTooLow_setsDefaultThreshold() throws Exception {
long thresholdTooLowBytes = 1L;
- NetworkTemplate[] templates = new NetworkTemplate[] { sTemplateWifi };
DataUsageRequest inputRequest = new DataUsageRequest(
- DataUsageRequest.REQUEST_ID_UNSET, templates, NO_UIDS, thresholdTooLowBytes);
+ DataUsageRequest.REQUEST_ID_UNSET, sTemplateWifi, thresholdTooLowBytes);
DataUsageRequest request = mStatsObservers.register(inputRequest, mMessenger, mockBinder,
Process.SYSTEM_UID, NetworkStatsAccess.Level.DEVICE);
assertTrue(request.requestId > 0);
- assertTrue(Arrays.deepEquals(templates, request.templates));
- assertNull(request.uids);
+ assertTrue(Objects.equals(sTemplateWifi, request.template));
assertEquals(THRESHOLD_BYTES, request.thresholdInBytes);
}
public void testRegister_highThreshold_accepted() throws Exception {
long highThresholdBytes = 2 * THRESHOLD_BYTES;
- NetworkTemplate[] templates = new NetworkTemplate[] { sTemplateWifi };
DataUsageRequest inputRequest = new DataUsageRequest(
- DataUsageRequest.REQUEST_ID_UNSET, templates, NO_UIDS, highThresholdBytes);
+ DataUsageRequest.REQUEST_ID_UNSET, sTemplateWifi, highThresholdBytes);
DataUsageRequest request = mStatsObservers.register(inputRequest, mMessenger, mockBinder,
Process.SYSTEM_UID, NetworkStatsAccess.Level.DEVICE);
assertTrue(request.requestId > 0);
- assertTrue(Arrays.deepEquals(templates, request.templates));
- assertNull(request.uids);
+ assertTrue(Objects.equals(sTemplateWifi, request.template));
assertEquals(highThresholdBytes, request.thresholdInBytes);
}
public void testRegister_twoRequests_twoIds() throws Exception {
- NetworkTemplate[] templates = new NetworkTemplate[] { sTemplateWifi };
DataUsageRequest inputRequest = new DataUsageRequest(
- DataUsageRequest.REQUEST_ID_UNSET, templates, NO_UIDS, THRESHOLD_BYTES);
+ DataUsageRequest.REQUEST_ID_UNSET, sTemplateWifi, THRESHOLD_BYTES);
DataUsageRequest request1 = mStatsObservers.register(inputRequest, mMessenger, mockBinder,
Process.SYSTEM_UID, NetworkStatsAccess.Level.DEVICE);
assertTrue(request1.requestId > 0);
- assertTrue(Arrays.deepEquals(templates, request1.templates));
- assertNull(request1.uids);
+ assertTrue(Objects.equals(sTemplateWifi, request1.template));
assertEquals(THRESHOLD_BYTES, request1.thresholdInBytes);
DataUsageRequest request2 = mStatsObservers.register(inputRequest, mMessenger, mockBinder,
Process.SYSTEM_UID, NetworkStatsAccess.Level.DEVICE);
assertTrue(request2.requestId > request1.requestId);
- assertTrue(Arrays.deepEquals(templates, request2.templates));
- assertNull(request2.uids);
+ assertTrue(Objects.equals(sTemplateWifi, request2.template));
assertEquals(THRESHOLD_BYTES, request2.thresholdInBytes);
}
- public void testRegister_defaultAccess_otherUids_securityException() throws Exception {
- NetworkTemplate[] templates = new NetworkTemplate[] { sTemplateImsi1 };
- int[] uids = new int[] { UID_RED, UID_BLUE, UID_GREEN };
- DataUsageRequest inputRequest = new DataUsageRequest(
- DataUsageRequest.REQUEST_ID_UNSET, templates, uids, THRESHOLD_BYTES);
-
- try {
- mStatsObservers.register(inputRequest, mMessenger, mockBinder, UID_RED,
- NetworkStatsAccess.Level.DEFAULT);
- fail("Should have denied access");
- } catch (SecurityException expected) {}
- }
-
- public void testRegister_userAccess_otherUidsSameUser()
- throws Exception {
- NetworkTemplate[] templates = new NetworkTemplate[] { sTemplateImsi1 };
- int[] uids = new int[] { UID_RED, UID_BLUE, UID_GREEN };
- DataUsageRequest inputRequest = new DataUsageRequest(
- DataUsageRequest.REQUEST_ID_UNSET, templates, uids, THRESHOLD_BYTES);
-
- DataUsageRequest request = mStatsObservers.register(inputRequest, mMessenger, mockBinder,
- UID_RED, NetworkStatsAccess.Level.USER);
- assertTrue(request.requestId > 0);
- assertTrue(Arrays.deepEquals(templates, request.templates));
- assertTrue(Arrays.equals(uids, request.uids));
- assertEquals(THRESHOLD_BYTES, request.thresholdInBytes);
- }
-
- public void testRegister_defaultAccess_sameUid() throws Exception {
- NetworkTemplate[] templates = new NetworkTemplate[] { sTemplateImsi1 };
- int[] uids = new int[] { UID_RED };
- DataUsageRequest inputRequest = new DataUsageRequest(
- DataUsageRequest.REQUEST_ID_UNSET, templates, uids, THRESHOLD_BYTES);
-
- DataUsageRequest request = mStatsObservers.register(inputRequest, mMessenger, mockBinder,
- UID_RED, NetworkStatsAccess.Level.DEFAULT);
- assertTrue(request.requestId > 0);
- assertTrue(Arrays.deepEquals(templates, request.templates));
- assertTrue(Arrays.equals(uids, request.uids));
- assertEquals(THRESHOLD_BYTES, request.thresholdInBytes);
- }
-
public void testUnregister_unknownRequest_noop() throws Exception {
- NetworkTemplate[] templates = new NetworkTemplate[] { sTemplateWifi };
DataUsageRequest unknownRequest = new DataUsageRequest(
- 123456 /* id */, templates, NO_UIDS, THRESHOLD_BYTES);
+ 123456 /* id */, sTemplateWifi, THRESHOLD_BYTES);
mStatsObservers.unregister(unknownRequest, UID_RED);
}
public void testUnregister_knownRequest_releasesCaller() throws Exception {
- NetworkTemplate[] templates = new NetworkTemplate[] { sTemplateImsi1 };
DataUsageRequest inputRequest = new DataUsageRequest(
- DataUsageRequest.REQUEST_ID_UNSET, templates, NO_UIDS, THRESHOLD_BYTES);
+ DataUsageRequest.REQUEST_ID_UNSET, sTemplateImsi1, THRESHOLD_BYTES);
DataUsageRequest request = mStatsObservers.register(inputRequest, mMessenger, mockBinder,
Process.SYSTEM_UID, NetworkStatsAccess.Level.DEVICE);
assertTrue(request.requestId > 0);
- assertTrue(Arrays.deepEquals(templates, request.templates));
- assertNull(request.uids);
+ assertTrue(Objects.equals(sTemplateImsi1, request.template));
assertEquals(THRESHOLD_BYTES, request.thresholdInBytes);
Mockito.verify(mockBinder).linkToDeath(any(IBinder.DeathRecipient.class), anyInt());
@@ -250,15 +197,13 @@
}
public void testUnregister_knownRequest_invalidUid_doesNotUnregister() throws Exception {
- NetworkTemplate[] templates = new NetworkTemplate[] { sTemplateImsi1 };
DataUsageRequest inputRequest = new DataUsageRequest(
- DataUsageRequest.REQUEST_ID_UNSET, templates, NO_UIDS, THRESHOLD_BYTES);
+ DataUsageRequest.REQUEST_ID_UNSET, sTemplateImsi1, THRESHOLD_BYTES);
DataUsageRequest request = mStatsObservers.register(inputRequest, mMessenger, mockBinder,
UID_RED, NetworkStatsAccess.Level.DEVICE);
assertTrue(request.requestId > 0);
- assertTrue(Arrays.deepEquals(templates, request.templates));
- assertNull(request.uids);
+ assertTrue(Objects.equals(sTemplateImsi1, request.template));
assertEquals(THRESHOLD_BYTES, request.thresholdInBytes);
Mockito.verify(mockBinder).linkToDeath(any(IBinder.DeathRecipient.class), anyInt());
@@ -269,15 +214,13 @@
}
public void testUpdateStats_initialSample_doesNotNotify() throws Exception {
- NetworkTemplate[] templates = new NetworkTemplate[] { sTemplateImsi1 };
DataUsageRequest inputRequest = new DataUsageRequest(
- DataUsageRequest.REQUEST_ID_UNSET, templates, NO_UIDS, THRESHOLD_BYTES);
+ DataUsageRequest.REQUEST_ID_UNSET, sTemplateImsi1, THRESHOLD_BYTES);
DataUsageRequest request = mStatsObservers.register(inputRequest, mMessenger, mockBinder,
Process.SYSTEM_UID, NetworkStatsAccess.Level.DEVICE);
assertTrue(request.requestId > 0);
- assertTrue(Arrays.deepEquals(templates, request.templates));
- assertNull(request.uids);
+ assertTrue(Objects.equals(sTemplateImsi1, request.template));
assertEquals(THRESHOLD_BYTES, request.thresholdInBytes);
NetworkIdentitySet identSet = new NetworkIdentitySet();
@@ -301,15 +244,13 @@
}
public void testUpdateStats_belowThreshold_doesNotNotify() throws Exception {
- NetworkTemplate[] templates = new NetworkTemplate[] { sTemplateImsi1 };
DataUsageRequest inputRequest = new DataUsageRequest(
- DataUsageRequest.REQUEST_ID_UNSET, templates, NO_UIDS, THRESHOLD_BYTES);
+ DataUsageRequest.REQUEST_ID_UNSET, sTemplateImsi1, THRESHOLD_BYTES);
DataUsageRequest request = mStatsObservers.register(inputRequest, mMessenger, mockBinder,
Process.SYSTEM_UID, NetworkStatsAccess.Level.DEVICE);
assertTrue(request.requestId > 0);
- assertTrue(Arrays.deepEquals(templates, request.templates));
- assertNull(request.uids);
+ assertTrue(Objects.equals(sTemplateImsi1, request.template));
assertEquals(THRESHOLD_BYTES, request.thresholdInBytes);
NetworkIdentitySet identSet = new NetworkIdentitySet();
@@ -339,16 +280,14 @@
assertEquals(INVALID_TYPE, mHandler.mLastMessageType);
}
- public void testUpdateStats_aboveThresholdNetwork_notifies() throws Exception {
- NetworkTemplate[] templates = new NetworkTemplate[] { sTemplateImsi1 };
+ public void testUpdateStats_deviceAccess_notifies() throws Exception {
DataUsageRequest inputRequest = new DataUsageRequest(
- DataUsageRequest.REQUEST_ID_UNSET, templates, NO_UIDS, THRESHOLD_BYTES);
+ DataUsageRequest.REQUEST_ID_UNSET, sTemplateImsi1, THRESHOLD_BYTES);
DataUsageRequest request = mStatsObservers.register(inputRequest, mMessenger, mockBinder,
Process.SYSTEM_UID, NetworkStatsAccess.Level.DEVICE);
assertTrue(request.requestId > 0);
- assertTrue(Arrays.deepEquals(templates, request.templates));
- assertNull(request.uids);
+ assertTrue(Objects.equals(sTemplateImsi1, request.template));
assertEquals(THRESHOLD_BYTES, request.thresholdInBytes);
NetworkIdentitySet identSet = new NetworkIdentitySet();
@@ -378,104 +317,14 @@
assertEquals(NetworkStatsManager.CALLBACK_LIMIT_REACHED, mHandler.mLastMessageType);
}
- public void testUpdateStats_aboveThresholdMultipleNetwork_notifies() throws Exception {
- NetworkTemplate[] templates = new NetworkTemplate[] { sTemplateImsi1, sTemplateImsi2 };
+ public void testUpdateStats_defaultAccess_notifiesSameUid() throws Exception {
DataUsageRequest inputRequest = new DataUsageRequest(
- DataUsageRequest.REQUEST_ID_UNSET, templates, NO_UIDS, THRESHOLD_BYTES);
-
- DataUsageRequest request = mStatsObservers.register(inputRequest, mMessenger, mockBinder,
- UID_RED, NetworkStatsAccess.Level.DEVICESUMMARY);
- assertTrue(request.requestId > 0);
- assertTrue(Arrays.deepEquals(templates, request.templates));
- assertNull(request.uids);
- assertEquals(THRESHOLD_BYTES, request.thresholdInBytes);
-
- NetworkIdentitySet identSet1 = new NetworkIdentitySet();
- identSet1.add(new NetworkIdentity(
- TYPE_MOBILE, TelephonyManager.NETWORK_TYPE_UNKNOWN,
- IMSI_1, null /* networkId */, false /* roaming */, true /* metered */));
- mActiveIfaces.put(TEST_IFACE, identSet1);
-
- NetworkIdentitySet identSet2 = new NetworkIdentitySet();
- identSet2.add(new NetworkIdentity(
- TYPE_MOBILE, TelephonyManager.NETWORK_TYPE_UNKNOWN,
- IMSI_2, null /* networkId */, false /* roaming */, true /* metered */));
- mActiveIfaces.put(TEST_IFACE2, identSet2);
-
- // Baseline
- NetworkStats xtSnapshot = new NetworkStats(TEST_START, 1 /* initialSize */)
- .addIfaceValues(TEST_IFACE, BASE_BYTES, 8L, BASE_BYTES, 16L)
- .addIfaceValues(TEST_IFACE2, BASE_BYTES + 1234L, 18L, BASE_BYTES, 12L);
- NetworkStats uidSnapshot = null;
- mStatsObservers.updateStats(
- xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces,
- VPN_INFO, TEST_START);
-
- // Delta - traffic on IMSI2
- xtSnapshot = new NetworkStats(TEST_START + MINUTE_IN_MILLIS, 1 /* initialSize */)
- .addIfaceValues(TEST_IFACE, BASE_BYTES, 8L, BASE_BYTES, 16L)
- .addIfaceValues(TEST_IFACE2, BASE_BYTES + THRESHOLD_BYTES, 22L,
- BASE_BYTES + THRESHOLD_BYTES, 24L);
- mStatsObservers.updateStats(
- xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces,
- VPN_INFO, TEST_START);
- waitForObserverToIdle();
-
- assertTrue(mCv.block(WAIT_TIMEOUT));
- assertEquals(NetworkStatsManager.CALLBACK_LIMIT_REACHED, mHandler.mLastMessageType);
- }
-
- public void testUpdateStats_aboveThresholdUid_notifies() throws Exception {
- NetworkTemplate[] templates = new NetworkTemplate[] { sTemplateImsi1 };
- int[] uids = new int[] { UID_RED, UID_BLUE, UID_GREEN };
- DataUsageRequest inputRequest = new DataUsageRequest(
- DataUsageRequest.REQUEST_ID_UNSET, templates, uids, THRESHOLD_BYTES);
-
- DataUsageRequest request = mStatsObservers.register(inputRequest, mMessenger, mockBinder,
- Process.SYSTEM_UID, NetworkStatsAccess.Level.DEVICE);
- assertTrue(request.requestId > 0);
- assertTrue(Arrays.deepEquals(templates, request.templates));
- assertTrue(Arrays.equals(uids,request.uids));
- assertEquals(THRESHOLD_BYTES, request.thresholdInBytes);
-
- NetworkIdentitySet identSet = new NetworkIdentitySet();
- identSet.add(new NetworkIdentity(
- TYPE_MOBILE, TelephonyManager.NETWORK_TYPE_UNKNOWN,
- IMSI_1, null /* networkId */, false /* roaming */, true /* metered */));
- mActiveUidIfaces.put(TEST_IFACE, identSet);
-
- // Baseline
- NetworkStats xtSnapshot = null;
- NetworkStats uidSnapshot = new NetworkStats(TEST_START, 2 /* initialSize */)
- .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, ROAMING_NO,
- BASE_BYTES, 2L, BASE_BYTES, 2L, 0L);
- mStatsObservers.updateStats(
- xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces,
- VPN_INFO, TEST_START);
-
- // Delta
- uidSnapshot = new NetworkStats(TEST_START+ 2 * MINUTE_IN_MILLIS, 2 /* initialSize */)
- .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, ROAMING_NO,
- BASE_BYTES + THRESHOLD_BYTES, 2L, BASE_BYTES + THRESHOLD_BYTES, 2L, 0L);
- mStatsObservers.updateStats(
- xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces,
- VPN_INFO, TEST_START);
- waitForObserverToIdle();
-
- assertTrue(mCv.block(WAIT_TIMEOUT));
- assertEquals(NetworkStatsManager.CALLBACK_LIMIT_REACHED, mHandler.mLastMessageType);
- }
-
- public void testUpdateStats_defaultAccess_noUid_notifiesSameUid() throws Exception {
- NetworkTemplate[] templates = new NetworkTemplate[] { sTemplateImsi1 };
- DataUsageRequest inputRequest = new DataUsageRequest(
- DataUsageRequest.REQUEST_ID_UNSET, templates, NO_UIDS, THRESHOLD_BYTES);
+ DataUsageRequest.REQUEST_ID_UNSET, sTemplateImsi1, THRESHOLD_BYTES);
DataUsageRequest request = mStatsObservers.register(inputRequest, mMessenger, mockBinder,
UID_RED, NetworkStatsAccess.Level.DEFAULT);
assertTrue(request.requestId > 0);
- assertTrue(Arrays.deepEquals(templates, request.templates));
- assertNull(request.uids);
+ assertTrue(Objects.equals(sTemplateImsi1, request.template));
assertEquals(THRESHOLD_BYTES, request.thresholdInBytes);
NetworkIdentitySet identSet = new NetworkIdentitySet();
@@ -494,7 +343,7 @@
VPN_INFO, TEST_START);
// Delta
- uidSnapshot = new NetworkStats(TEST_START+ 2 * MINUTE_IN_MILLIS, 2 /* initialSize */)
+ uidSnapshot = new NetworkStats(TEST_START + 2 * MINUTE_IN_MILLIS, 2 /* initialSize */)
.addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, ROAMING_NO,
BASE_BYTES + THRESHOLD_BYTES, 2L, BASE_BYTES + THRESHOLD_BYTES, 2L, 0L);
mStatsObservers.updateStats(
@@ -506,16 +355,14 @@
assertEquals(NetworkStatsManager.CALLBACK_LIMIT_REACHED, mHandler.mLastMessageType);
}
- public void testUpdateStats_defaultAccess_noUid_usageOtherUid_doesNotNotify() throws Exception {
- NetworkTemplate[] templates = new NetworkTemplate[] { sTemplateImsi1 };
+ public void testUpdateStats_defaultAccess_usageOtherUid_doesNotNotify() throws Exception {
DataUsageRequest inputRequest = new DataUsageRequest(
- DataUsageRequest.REQUEST_ID_UNSET, templates, NO_UIDS, THRESHOLD_BYTES);
+ DataUsageRequest.REQUEST_ID_UNSET, sTemplateImsi1, THRESHOLD_BYTES);
DataUsageRequest request = mStatsObservers.register(inputRequest, mMessenger, mockBinder,
UID_BLUE, NetworkStatsAccess.Level.DEFAULT);
assertTrue(request.requestId > 0);
- assertTrue(Arrays.deepEquals(templates, request.templates));
- assertNull(request.uids);
+ assertTrue(Objects.equals(sTemplateImsi1, request.template));
assertEquals(THRESHOLD_BYTES, request.thresholdInBytes);
NetworkIdentitySet identSet = new NetworkIdentitySet();
@@ -534,7 +381,7 @@
VPN_INFO, TEST_START);
// Delta
- uidSnapshot = new NetworkStats(TEST_START+ 2 * MINUTE_IN_MILLIS, 2 /* initialSize */)
+ uidSnapshot = new NetworkStats(TEST_START + 2 * MINUTE_IN_MILLIS, 2 /* initialSize */)
.addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, ROAMING_NO,
BASE_BYTES + THRESHOLD_BYTES, 2L, BASE_BYTES + THRESHOLD_BYTES, 2L, 0L);
mStatsObservers.updateStats(
@@ -547,15 +394,13 @@
}
public void testUpdateStats_userAccess_usageSameUser_notifies() throws Exception {
- NetworkTemplate[] templates = new NetworkTemplate[] { sTemplateImsi1 };
DataUsageRequest inputRequest = new DataUsageRequest(
- DataUsageRequest.REQUEST_ID_UNSET, templates, NO_UIDS, THRESHOLD_BYTES);
+ DataUsageRequest.REQUEST_ID_UNSET, sTemplateImsi1, THRESHOLD_BYTES);
DataUsageRequest request = mStatsObservers.register(inputRequest, mMessenger, mockBinder,
UID_BLUE, NetworkStatsAccess.Level.USER);
assertTrue(request.requestId > 0);
- assertTrue(Arrays.deepEquals(templates, request.templates));
- assertNull(request.uids);
+ assertTrue(Objects.equals(sTemplateImsi1, request.template));
assertEquals(THRESHOLD_BYTES, request.thresholdInBytes);
NetworkIdentitySet identSet = new NetworkIdentitySet();
@@ -574,7 +419,7 @@
VPN_INFO, TEST_START);
// Delta
- uidSnapshot = new NetworkStats(TEST_START+ 2 * MINUTE_IN_MILLIS, 2 /* initialSize */)
+ uidSnapshot = new NetworkStats(TEST_START + 2 * MINUTE_IN_MILLIS, 2 /* initialSize */)
.addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, ROAMING_NO,
BASE_BYTES + THRESHOLD_BYTES, 2L, BASE_BYTES + THRESHOLD_BYTES, 2L, 0L);
mStatsObservers.updateStats(
@@ -587,15 +432,13 @@
}
public void testUpdateStats_userAccess_usageAnotherUser_doesNotNotify() throws Exception {
- NetworkTemplate[] templates = new NetworkTemplate[] { sTemplateImsi1 };
DataUsageRequest inputRequest = new DataUsageRequest(
- DataUsageRequest.REQUEST_ID_UNSET, templates, NO_UIDS, THRESHOLD_BYTES);
+ DataUsageRequest.REQUEST_ID_UNSET, sTemplateImsi1, THRESHOLD_BYTES);
DataUsageRequest request = mStatsObservers.register(inputRequest, mMessenger, mockBinder,
UID_RED, NetworkStatsAccess.Level.USER);
assertTrue(request.requestId > 0);
- assertTrue(Arrays.deepEquals(templates, request.templates));
- assertNull(request.uids);
+ assertTrue(Objects.equals(sTemplateImsi1, request.template));
assertEquals(THRESHOLD_BYTES, request.thresholdInBytes);
NetworkIdentitySet identSet = new NetworkIdentitySet();
@@ -614,7 +457,7 @@
VPN_INFO, TEST_START);
// Delta
- uidSnapshot = new NetworkStats(TEST_START+ 2 * MINUTE_IN_MILLIS, 2 /* initialSize */)
+ uidSnapshot = new NetworkStats(TEST_START + 2 * MINUTE_IN_MILLIS, 2 /* initialSize */)
.addValues(TEST_IFACE, UID_ANOTHER_USER, SET_DEFAULT, TAG_NONE, ROAMING_NO,
BASE_BYTES + THRESHOLD_BYTES, 2L, BASE_BYTES + THRESHOLD_BYTES, 2L, 0L);
mStatsObservers.updateStats(
diff --git a/services/tests/servicestests/src/com/android/server/net/NetworkStatsServiceTest.java b/services/tests/servicestests/src/com/android/server/net/NetworkStatsServiceTest.java
index 74c1984..94c6711 100644
--- a/services/tests/servicestests/src/com/android/server/net/NetworkStatsServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/net/NetworkStatsServiceTest.java
@@ -100,7 +100,7 @@
import java.io.File;
import java.util.ArrayList;
-import java.util.Arrays;
+import java.util.Objects;
import java.util.List;
/**
@@ -887,7 +887,7 @@
}
- public void testRegisterDataUsageCallback_network() throws Exception {
+ public void testRegisterUsageCallback() throws Exception {
// pretend that wifi network comes online; service should ask about full
// network state, and poll any existing interfaces before updating.
expectCurrentTime();
@@ -907,9 +907,8 @@
String callingPackage = "the.calling.package";
long thresholdInBytes = 1L; // very small; should be overriden by framework
- NetworkTemplate[] templates = new NetworkTemplate[] { sTemplateWifi };
DataUsageRequest inputRequest = new DataUsageRequest(
- DataUsageRequest.REQUEST_ID_UNSET, templates, null /* uids */, thresholdInBytes);
+ DataUsageRequest.REQUEST_ID_UNSET, sTemplateWifi, thresholdInBytes);
// Create a messenger that waits for callback activity
ConditionVariable cv = new ConditionVariable(false);
@@ -931,11 +930,10 @@
// Register and verify request and that binder was called
DataUsageRequest request =
- mService.registerDataUsageCallback(callingPackage, inputRequest,
+ mService.registerUsageCallback(callingPackage, inputRequest,
messenger, mockBinder);
assertTrue(request.requestId > 0);
- assertTrue(Arrays.deepEquals(templates, request.templates));
- assertNull(request.uids);
+ assertTrue(Objects.equals(sTemplateWifi, request.template));
long minThresholdInBytes = 2 * 1024 * 1024; // 2 MB
assertEquals(minThresholdInBytes, request.thresholdInBytes);
@@ -997,7 +995,7 @@
EasyMock.replay(mockBinder);
// Unregister request
- mService.unregisterDataUsageRequest(request);
+ mService.unregisterUsageRequest(request);
// Wait for the caller to ack receipt of CALLBACK_RELEASED
assertTrue(cv.block(WAIT_TIMEOUT));
@@ -1007,157 +1005,13 @@
EasyMock.verify(mockBinder);
}
- public void testRegisterDataUsageCallback_uids() throws Exception {
- // pretend that network comes online
- expectCurrentTime();
- expectDefaultSettings();
- expectNetworkState(buildMobile3gState(IMSI_1, true /* isRoaming */));
- expectNetworkStatsSummary(buildEmptyStats());
- expectNetworkStatsUidDetail(buildEmptyStats());
- expectNetworkStatsPoll();
- expectBandwidthControlCheck();
-
- replay();
- mService.forceUpdateIfaces();
- verifyAndReset();
-
+ public void testUnregisterUsageCallback_unknown_noop() throws Exception {
String callingPackage = "the.calling.package";
long thresholdInBytes = 10 * 1024 * 1024; // 10 MB
- NetworkTemplate[] templates = new NetworkTemplate[] { sTemplateImsi1, sTemplateImsi2 };
- int[] uids = new int[] { UID_RED };
- DataUsageRequest inputRequest = new DataUsageRequest(
- DataUsageRequest.REQUEST_ID_UNSET, templates, uids, thresholdInBytes);
-
- // Create a messenger that waits for callback activity
- ConditionVariable cv = new ConditionVariable(false);
- cv.close();
- LatchedHandler latchedHandler = new LatchedHandler(Looper.getMainLooper(), cv);
- Messenger messenger = new Messenger(latchedHandler);
-
- // Allow binder to connect
- IBinder mockBinder = createMock(IBinder.class);
- mockBinder.linkToDeath((IBinder.DeathRecipient) anyObject(), anyInt());
- EasyMock.replay(mockBinder);
-
- // Force poll
- expectCurrentTime();
- expectDefaultSettings();
- expectNetworkStatsSummary(buildEmptyStats());
- expectNetworkStatsUidDetail(buildEmptyStats());
- expectNetworkStatsPoll();
- replay();
-
- // Register and verify request and that binder was called
- DataUsageRequest request =
- mService.registerDataUsageCallback(callingPackage, inputRequest,
- messenger, mockBinder);
- assertTrue(request.requestId > 0);
- assertTrue(Arrays.deepEquals(templates, request.templates));
- assertTrue(Arrays.equals(uids, request.uids));
- assertEquals(thresholdInBytes, request.thresholdInBytes);
-
- // Wait for service to handle internal MSG_REGISTER_DATA_USAGE_LISTENER
- mHandler.sendMessage(mHandler.obtainMessage(-1));
- mHandlerThread.waitForIdle(WAIT_TIMEOUT);
-
- verifyAndReset();
-
- // Make sure that the caller binder gets connected
- EasyMock.verify(mockBinder);
- EasyMock.reset(mockBinder);
-
- // modify some number on mobile interface, and trigger poll event
- // not enough traffic to call data usage callback
- incrementCurrentTime(HOUR_IN_MILLIS);
- expectCurrentTime();
- expectDefaultSettings();
- expectNetworkStatsSummary(buildEmptyStats());
- expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1)
- .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, ROAMING_NO, 128L, 2L,
- 128L, 2L, 0L)
- .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, ROAMING_NO, 64L, 1L, 64L,
- 1L, 0L));
- expectNetworkStatsPoll();
-
- replay();
- forcePollAndWaitForIdle();
-
- // verify service recorded history
- assertUidTotal(sTemplateImsi1, UID_RED, 128L, 2L, 128L, 2L, 0);
-
- // verify entire history present
- NetworkStats stats = mSession.getSummaryForAllUid(
- sTemplateImsi1, Long.MIN_VALUE, Long.MAX_VALUE, true);
- assertEquals(2, stats.size());
- assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, TAG_NONE, ROAMING_YES, 128L, 2L,
- 128L, 2L, 0);
- assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, 0xF00D, ROAMING_YES, 64L, 1L, 64L,
- 1L, 0);
-
- verifyAndReset();
-
- // make sure callback has not being called
- assertEquals(INVALID_TYPE, latchedHandler.mLastMessageType);
-
- // and bump forward again, with counters going higher. this is
- // important, since it will trigger the data usage callback
- incrementCurrentTime(DAY_IN_MILLIS);
- expectCurrentTime();
- expectDefaultSettings();
- expectNetworkStatsSummary(buildEmptyStats());
- expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1)
- .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, ROAMING_NO,
- 128000000L, 2L, 128000000L, 2L, 0L)
- .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, ROAMING_NO,
- 64000000L, 1L, 64000000L, 1L, 0L));
- expectNetworkStatsPoll();
-
- replay();
- forcePollAndWaitForIdle();
-
- // verify service recorded history
- assertUidTotal(sTemplateImsi1, UID_RED, 128000000L, 2L, 128000000L, 2L, 0);
-
- // verify entire history present
- stats = mSession.getSummaryForAllUid(
- sTemplateImsi1, Long.MIN_VALUE, Long.MAX_VALUE, true);
- assertEquals(2, stats.size());
- assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, TAG_NONE, ROAMING_YES,
- 128000000L, 2L, 128000000L, 2L, 0);
- assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, 0xF00D, ROAMING_YES,
- 64000000L, 1L, 64000000L, 1L, 0);
-
- verifyAndReset();
-
- // Wait for the caller to ack receipt of CALLBACK_LIMIT_REACHED
- assertTrue(cv.block(WAIT_TIMEOUT));
- assertEquals(NetworkStatsManager.CALLBACK_LIMIT_REACHED, latchedHandler.mLastMessageType);
- cv.close();
-
- // Allow binder to disconnect
- expect(mockBinder.unlinkToDeath((IBinder.DeathRecipient) anyObject(), anyInt()))
- .andReturn(true);
- EasyMock.replay(mockBinder);
-
- // Unregister request
- mService.unregisterDataUsageRequest(request);
-
- // Wait for the caller to ack receipt of CALLBACK_RELEASED
- assertTrue(cv.block(WAIT_TIMEOUT));
- assertEquals(NetworkStatsManager.CALLBACK_RELEASED, latchedHandler.mLastMessageType);
-
- // Make sure that the caller binder gets disconnected
- EasyMock.verify(mockBinder);
- }
-
- public void testUnregisterDataUsageCallback_unknown_noop() throws Exception {
- String callingPackage = "the.calling.package";
- long thresholdInBytes = 10 * 1024 * 1024; // 10 MB
- NetworkTemplate[] templates = new NetworkTemplate[] { sTemplateImsi1, sTemplateImsi2 };
DataUsageRequest unknownRequest = new DataUsageRequest(
- 2, templates, null /* uids */, thresholdInBytes);
+ 2 /* requestId */, sTemplateImsi1, thresholdInBytes);
- mService.unregisterDataUsageRequest(unknownRequest);
+ mService.unregisterUsageRequest(unknownRequest);
}
private static File getBaseDir(File statsDir) {
diff --git a/tools/fonts/fontchain_lint.py b/tools/fonts/fontchain_lint.py
index fe7c3b9..ea36e2c 100755
--- a/tools/fonts/fontchain_lint.py
+++ b/tools/fonts/fontchain_lint.py
@@ -412,8 +412,9 @@
path.join(ucd_path, 'emoji-zwj-sequences.txt'))
# filter modern pentathlon, as it seems likely to be removed from final spec
+ # also filter rifle
def is_excluded(n):
- return n == 0x1f93b
+ return n in [0x1f93b, 0x1f946]
def contains_excluded(t):
if type(t) == int: