summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--api/current.txt41
-rw-r--r--api/removed.txt31
-rw-r--r--api/system-current.txt41
-rw-r--r--api/system-removed.txt31
-rw-r--r--api/test-current.txt41
-rw-r--r--api/test-removed.txt31
-rw-r--r--cmds/am/src/com/android/commands/am/Am.java8
-rw-r--r--core/java/android/accessibilityservice/AccessibilityService.java2
-rw-r--r--core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl2
-rw-r--r--core/java/android/app/Activity.java32
-rw-r--r--core/java/android/app/ActivityManager.java2
-rw-r--r--core/java/android/app/ActivityManagerNative.java31
-rw-r--r--core/java/android/app/ActivityThread.java30
-rw-r--r--core/java/android/app/AppOpsManager.java55
-rw-r--r--core/java/android/app/ApplicationThreadNative.java6
-rw-r--r--core/java/android/app/IActivityManager.java7
-rw-r--r--core/java/android/app/IApplicationThread.java4
-rw-r--r--core/java/android/app/LoadedApk.java6
-rw-r--r--core/java/android/app/usage/DataUsagePolicy.java1
-rw-r--r--core/java/android/app/usage/NetworkStats.java14
-rw-r--r--core/java/android/app/usage/NetworkStatsManager.java219
-rw-r--r--core/java/android/bluetooth/le/ScanFilter.java14
-rw-r--r--core/java/android/net/DataUsageRequest.java63
-rw-r--r--core/java/android/net/INetworkPolicyListener.aidl1
-rw-r--r--core/java/android/net/INetworkPolicyManager.aidl1
-rw-r--r--core/java/android/net/INetworkStatsService.aidl4
-rw-r--r--core/java/android/net/NetworkPolicyManager.java57
-rw-r--r--core/java/android/net/network-policy-restrictions.md47
-rw-r--r--core/java/android/os/health/HealthStats.java4
-rw-r--r--core/java/android/os/health/PackageHealthStats.java2
-rw-r--r--core/java/android/os/health/PidHealthStats.java38
-rw-r--r--core/java/android/os/health/ProcessHealthStats.java21
-rw-r--r--core/java/android/os/health/ServiceHealthStats.java11
-rw-r--r--core/java/android/os/health/SystemHealthManager.java7
-rw-r--r--core/java/android/os/health/TimerStat.java4
-rw-r--r--core/java/android/os/health/UidHealthStats.java177
-rw-r--r--core/java/android/text/StaticLayout.java12
-rw-r--r--core/java/android/view/ViewRootImpl.java12
-rw-r--r--core/java/android/widget/RadialTimePickerView.java7
-rw-r--r--core/jni/android_hardware_location_ContextHubService.cpp20
-rw-r--r--core/res/AndroidManifest.xml7
-rw-r--r--core/res/res/layout/notification_material_action_list.xml2
-rw-r--r--core/res/res/values-be-rBY/strings.xml16
-rw-r--r--core/res/res/values-es/strings.xml6
-rw-r--r--core/res/res/values-fa/strings.xml2
-rw-r--r--core/res/res/values-gl-rES/strings.xml2
-rw-r--r--core/res/res/values-hy-rAM/strings.xml4
-rw-r--r--core/res/res/values-iw/strings.xml2
-rw-r--r--core/res/res/values-kk-rKZ/strings.xml2
-rw-r--r--core/res/res/values-sq-rAL/strings.xml6
-rw-r--r--core/res/res/values/dimens.xml3
-rw-r--r--core/res/res/values/symbols.xml2
-rw-r--r--core/tests/coretests/src/android/net/NetworkPolicyManagerTest.java107
-rw-r--r--docs/html/_redirects.yaml363
-rw-r--r--docs/html/jd_collections.js16
-rw-r--r--docs/html/jd_extras_en.js329
-rw-r--r--docs/html/training/camera/photobasics.jd62
-rw-r--r--docs/html/wear/preview/_book.yaml25
-rw-r--r--docs/html/wear/preview/api-overview.jd124
-rw-r--r--docs/html/wear/preview/downloads.jd457
-rw-r--r--docs/html/wear/preview/features/complications.jd7
-rw-r--r--docs/html/wear/preview/features/ime.jd7
-rw-r--r--docs/html/wear/preview/features/notifications.jd7
-rw-r--r--docs/html/wear/preview/features/ui-nav-actions.jd7
-rw-r--r--docs/html/wear/preview/images/hero-1x.pngbin0 -> 169371 bytes
-rw-r--r--docs/html/wear/preview/images/hero-2x.pngbin0 -> 519690 bytes
-rw-r--r--docs/html/wear/preview/index.jd106
-rw-r--r--docs/html/wear/preview/license.jd145
-rw-r--r--docs/html/wear/preview/preview_toc.cs132
-rw-r--r--docs/html/wear/preview/program.jd62
-rw-r--r--docs/html/wear/preview/start.jd139
-rw-r--r--docs/html/wear/wear_toc.cs81
-rw-r--r--graphics/java/android/graphics/Bitmap.java2
-rw-r--r--graphics/java/android/graphics/Canvas.java2
-rw-r--r--graphics/java/android/graphics/Paint.java2
-rw-r--r--graphics/java/android/graphics/drawable/DrawableContainer.java8
-rw-r--r--media/java/android/media/AudioRoutesInfo.java17
-rw-r--r--media/java/android/media/MediaRouter.java5
-rw-r--r--media/java/android/media/browse/MediaBrowser.java11
-rw-r--r--media/java/android/media/tv/TvContract.java6
-rw-r--r--media/java/android/media/tv/TvInputService.java39
-rw-r--r--media/java/android/service/media/IMediaBrowserService.aidl5
-rw-r--r--media/java/android/service/media/IMediaBrowserServiceCallbacks.aidl3
-rw-r--r--media/java/android/service/media/MediaBrowserService.java12
-rw-r--r--media/jni/android_media_Utils.cpp4
-rw-r--r--packages/DocumentsUI/Android.mk2
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java4
-rw-r--r--packages/ExtServices/src/android/ext/services/notification/Ranker.java7
-rw-r--r--packages/MtpDocumentsProvider/Android.mk2
-rw-r--r--packages/SettingsLib/res/values-gl-rES/strings.xml2
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java2
-rw-r--r--packages/SystemUI/AndroidManifest.xml1
-rw-r--r--packages/SystemUI/res/layout/keyguard_user_switcher.xml11
-rw-r--r--packages/SystemUI/res/layout/keyguard_user_switcher_inner.xml27
-rw-r--r--packages/SystemUI/res/layout/quick_settings_brightness_dialog.xml1
-rw-r--r--packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml13
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java19
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/events/ui/dragndrop/DragEndCancelledEvent.java39
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java39
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/model/Task.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/model/TaskKeyLruCache.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java22
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvActivity.java16
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/tv/animations/DismissAnimationsHolder.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/tv/animations/RecentsRowFocusAnimationHolder.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskStackHorizontalViewAdapter.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java77
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/SystemBarScrimViews.java17
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java91
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java18
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java48
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/ActionListTransformState.java60
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTemplateViewWrapper.java22
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationViewWrapper.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/TransformState.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java19
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java49
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java20
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/DataSaverController.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcher.java35
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherScrim.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/UserInfoController.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java13
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java79
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/stack/ScrollContainer.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java5
-rw-r--r--proto/src/metrics_constants.proto15
-rw-r--r--services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java65
-rw-r--r--services/accessibility/java/com/android/server/accessibility/MagnificationController.java13
-rw-r--r--services/core/java/com/android/server/AlarmManagerService.java2
-rw-r--r--services/core/java/com/android/server/ConnectivityService.java91
-rw-r--r--services/core/java/com/android/server/LockSettingsService.java3
-rw-r--r--services/core/java/com/android/server/NetworkManagementService.java18
-rw-r--r--services/core/java/com/android/server/accounts/AccountManagerService.java18
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java64
-rw-r--r--services/core/java/com/android/server/am/ActivityStack.java7
-rw-r--r--services/core/java/com/android/server/am/RecentTasks.java5
-rw-r--r--services/core/java/com/android/server/am/ServiceRecord.java6
-rw-r--r--services/core/java/com/android/server/fingerprint/FingerprintService.java2
-rw-r--r--services/core/java/com/android/server/job/controllers/ConnectivityController.java5
-rw-r--r--services/core/java/com/android/server/job/controllers/IdleController.java10
-rw-r--r--services/core/java/com/android/server/net/NetworkPolicyManagerService.java208
-rw-r--r--services/core/java/com/android/server/net/NetworkStatsObservers.java76
-rw-r--r--services/core/java/com/android/server/net/NetworkStatsService.java12
-rw-r--r--services/core/java/com/android/server/pm/BackgroundDexOptService.java9
-rw-r--r--services/core/java/com/android/server/pm/PackageDexOptimizer.java27
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java95
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerShellCommand.java76
-rw-r--r--services/core/java/com/android/server/policy/PhoneWindowManager.java2
-rw-r--r--services/core/java/com/android/server/vr/VrManagerService.java207
-rw-r--r--services/core/java/com/android/server/wm/AppWindowAnimator.java3
-rw-r--r--services/core/java/com/android/server/wm/AppWindowToken.java65
-rw-r--r--services/core/java/com/android/server/wm/DisplayContent.java3
-rw-r--r--services/core/java/com/android/server/wm/DockedStackDividerController.java10
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerDebugConfig.java2
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java37
-rw-r--r--services/core/java/com/android/server/wm/WindowState.java70
-rw-r--r--services/core/java/com/android/server/wm/WindowStateAnimator.java40
-rw-r--r--services/core/java/com/android/server/wm/WindowSurfacePlacer.java14
-rw-r--r--services/midi/java/com/android/server/midi/MidiService.java19
-rw-r--r--services/tests/servicestests/src/com/android/server/net/NetworkStatsObserversTest.java225
-rw-r--r--services/tests/servicestests/src/com/android/server/net/NetworkStatsServiceTest.java164
-rw-r--r--services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java6
-rw-r--r--tests/UiBench/AndroidManifest.xml11
-rw-r--r--tests/UiBench/src/com/android/test/uibench/ScrollableWebViewActivity.java35
-rwxr-xr-xtools/fonts/fontchain_lint.py3
175 files changed, 4553 insertions, 1567 deletions
diff --git a/api/current.txt b/api/current.txt
index d380e70d6a01..e9d5c3df9318 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -6417,22 +6417,6 @@ package android.app.usage {
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 @@ package android.app.usage {
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 @@ package android.app.usage {
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 @@ package android.net {
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 f9fce40f642d..2673a829cacd 100644
--- a/api/removed.txt
+++ b/api/removed.txt
@@ -17,6 +17,37 @@ package android.app.admin {
}
+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 dbbefbf934cb..e5c88cca2b84 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -6698,22 +6698,6 @@ package android.app.usage {
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 @@ package android.app.usage {
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 @@ package android.app.usage {
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 @@ package android.net {
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 6897ce0571aa..7f2c2d6c6199 100644
--- a/api/system-removed.txt
+++ b/api/system-removed.txt
@@ -15,6 +15,37 @@ package android.app.admin {
}
+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 acd729913df0..ff2a41c1761a 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -6422,22 +6422,6 @@ package android.app.usage {
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 @@ package android.app.usage {
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 @@ package android.app.usage {
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 @@ package android.net {
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 f9fce40f642d..2673a829cacd 100644
--- a/api/test-removed.txt
+++ b/api/test-removed.txt
@@ -17,6 +17,37 @@ package android.app.admin {
}
+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/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index 0bcee86be7d8..8ccd5d2ebcba 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -1598,10 +1598,10 @@ public class Am extends BaseCommand {
}
System.out.println("Performing idle maintenance...");
- Intent intent = new Intent(
- "com.android.server.task.controllers.IdleController.ACTION_TRIGGER_IDLE");
- mAm.broadcastIntent(null, intent, null, null, 0, null, null, null,
- android.app.AppOpsManager.OP_NONE, null, true, false, UserHandle.USER_ALL);
+ try {
+ mAm.sendIdleJobTrigger();
+ } catch (RemoteException e) {
+ }
}
private void runScreenCompat() throws Exception {
diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java
index 8b277b2a12ea..ae78e21807e8 100644
--- a/core/java/android/accessibilityservice/AccessibilityService.java
+++ b/core/java/android/accessibilityservice/AccessibilityService.java
@@ -949,7 +949,7 @@ public abstract class AccessibilityService extends Service {
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 3783fcac5569..7a55079d3ecf 100644
--- a/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl
+++ b/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl
@@ -75,7 +75,7 @@ interface IAccessibilityServiceConnection {
float getMagnificationCenterY();
- Region getMagnifiedRegion();
+ Region getMagnificationRegion();
boolean resetMagnification(boolean animate);
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 9b4c8bd070d8..07d3b8acd85e 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -1879,14 +1879,9 @@ public class Activity extends ContextThemeWrapper
*
* @param isInMultiWindowMode True if the activity is in multi-window mode.
*/
- @CallSuper
public void onMultiWindowModeChanged(boolean isInMultiWindowMode) {
- if (DEBUG_LIFECYCLE) Slog.v(TAG,
- "onMultiWindowModeChanged " + this + ": " + isInMultiWindowMode);
- mFragments.dispatchMultiWindowModeChanged(isInMultiWindowMode);
- if (mWindow != null) {
- mWindow.onMultiWindowModeChanged();
- }
+ // Left deliberately empty. There should be no side effects if a direct
+ // subclass of Activity does not call super.
}
/**
@@ -1909,11 +1904,9 @@ public class Activity extends ContextThemeWrapper
*
* @param isInPictureInPictureMode True if the activity is in picture-in-picture mode.
*/
- @CallSuper
public void onPictureInPictureModeChanged(boolean isInPictureInPictureMode) {
- if (DEBUG_LIFECYCLE) Slog.v(TAG,
- "onPictureInPictureModeChanged " + this + ": " + isInPictureInPictureMode);
- mFragments.dispatchPictureInPictureModeChanged(isInPictureInPictureMode);
+ // Left deliberately empty. There should be no side effects if a direct
+ // subclass of Activity does not call super.
}
/**
@@ -6875,6 +6868,23 @@ public class Activity extends ContextThemeWrapper
}
}
+ final void dispatchMultiWindowModeChanged(boolean isInMultiWindowMode) {
+ if (DEBUG_LIFECYCLE) Slog.v(TAG,
+ "dispatchMultiWindowModeChanged " + this + ": " + isInMultiWindowMode);
+ mFragments.dispatchMultiWindowModeChanged(isInMultiWindowMode);
+ if (mWindow != null) {
+ mWindow.onMultiWindowModeChanged();
+ }
+ onMultiWindowModeChanged(isInMultiWindowMode);
+ }
+
+ final void dispatchPictureInPictureModeChanged(boolean isInPictureInPictureMode) {
+ if (DEBUG_LIFECYCLE) Slog.v(TAG,
+ "dispatchPictureInPictureModeChanged " + this + ": " + isInPictureInPictureMode);
+ mFragments.dispatchPictureInPictureModeChanged(isInPictureInPictureMode);
+ onPictureInPictureModeChanged(isInPictureInPictureMode);
+ }
+
/**
* @hide
*/
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index ff8cf66770eb..8a92b5477caf 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -901,7 +901,7 @@ public class ActivityManager {
*/
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/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 1a7c7467633f..a4f404f18ed6 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -1527,7 +1527,9 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
case SET_LOCK_SCREEN_SHOWN_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
- setLockScreenShown(data.readInt() != 0);
+ final boolean showing = data.readInt() != 0;
+ final boolean occluded = data.readInt() != 0;
+ setLockScreenShown(showing, occluded);
reply.writeNoException();
return true;
}
@@ -2416,8 +2418,9 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
Bundle receiverExtras = data.readBundle();
IBinder activityToken = data.readStrongBinder();
boolean focused = data.readInt() == 1;
+ boolean newSessionId = data.readInt() == 1;
boolean res = requestAssistContextExtras(requestType, receiver, receiverExtras,
- activityToken, focused);
+ activityToken, focused, newSessionId);
reply.writeNoException();
reply.writeInt(res ? 1 : 0);
return true;
@@ -2968,6 +2971,12 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
reply.writeNoException();
return true;
}
+ case SEND_IDLE_JOB_TRIGGER_TRANSACTION: {
+ data.enforceInterface(IActivityManager.descriptor);
+ sendIdleJobTrigger();
+ reply.writeNoException();
+ return true;
+ }
}
return super.onTransact(code, data, reply, flags);
@@ -4922,12 +4931,13 @@ class ActivityManagerProxy implements IActivityManager
reply.recycle();
return pfd;
}
- public void setLockScreenShown(boolean shown) throws RemoteException
+ public void setLockScreenShown(boolean showing, boolean occluded) throws RemoteException
{
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
- data.writeInt(shown ? 1 : 0);
+ data.writeInt(showing ? 1 : 0);
+ data.writeInt(occluded ? 1 : 0);
mRemote.transact(SET_LOCK_SCREEN_SHOWN_TRANSACTION, data, reply, 0);
reply.readException();
data.recycle();
@@ -6095,7 +6105,7 @@ class ActivityManagerProxy implements IActivityManager
public boolean requestAssistContextExtras(int requestType, IResultReceiver receiver,
Bundle receiverExtras,
- IBinder activityToken, boolean focused) throws RemoteException {
+ IBinder activityToken, boolean focused, boolean newSessionId) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
@@ -6104,6 +6114,7 @@ class ActivityManagerProxy implements IActivityManager
data.writeBundle(receiverExtras);
data.writeStrongBinder(activityToken);
data.writeInt(focused ? 1 : 0);
+ data.writeInt(newSessionId ? 1 : 0);
mRemote.transact(REQUEST_ASSIST_CONTEXT_EXTRAS_TRANSACTION, data, reply, 0);
reply.readException();
boolean res = reply.readInt() != 0;
@@ -6244,6 +6255,16 @@ class ActivityManagerProxy implements IActivityManager
reply.recycle();
}
+ public void sendIdleJobTrigger() throws RemoteException {
+ Parcel data = Parcel.obtain();
+ Parcel reply = Parcel.obtain();
+ data.writeInterfaceToken(IActivityManager.descriptor);
+ mRemote.transact(SEND_IDLE_JOB_TRIGGER_TRANSACTION, data, reply, 0);
+ reply.readException();
+ data.recycle();
+ reply.recycle();
+ }
+
public IActivityContainer createVirtualActivityContainer(IBinder parentActivityToken,
IActivityContainerCallback callback) throws RemoteException {
Parcel data = Parcel.obtain();
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index cf2ef4521291..061d924fa529 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -206,7 +206,8 @@ public final class ActivityThread {
ActivityClientRecord mNewActivities = null;
// Number of activities that are currently visible on-screen.
int mNumVisibleActivities = 0;
- WeakReference<AssistStructure> mLastAssistStructure;
+ ArrayList<WeakReference<AssistStructure>> mLastAssistStructures = new ArrayList<>();
+ private int mLastSessionId;
final ArrayMap<IBinder, Service> mServices = new ArrayMap<>();
AppBindData mBoundApplication;
Profiler mProfiler;
@@ -557,8 +558,9 @@ public final class ActivityThread {
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);
@@ -621,6 +623,7 @@ public final class ActivityThread {
IBinder activityToken;
IBinder requestToken;
int requestType;
+ int sessionId;
}
static final class ActivityConfigChangeData {
@@ -1182,11 +1185,12 @@ public final class ActivityThread {
@Override
public void requestAssistContextExtras(IBinder activityToken, IBinder requestToken,
- int requestType) {
+ int requestType, int sessionId) {
RequestAssistContextExtras cmd = new RequestAssistContextExtras();
cmd.activityToken = activityToken;
cmd.requestToken = requestToken;
cmd.requestType = requestType;
+ cmd.sessionId = sessionId;
sendMessage(H.REQUEST_ASSIST_CONTEXT_EXTRAS, cmd);
}
@@ -1803,6 +1807,7 @@ public final class ActivityThread {
}
private Configuration mMainThreadConfig = new Configuration();
+
Configuration applyConfigCompatMainThread(int displayDensity, Configuration config,
CompatibilityInfo compat) {
if (config == null) {
@@ -2784,10 +2789,15 @@ public final class ActivityThread {
}
public void handleRequestAssistContextExtras(RequestAssistContextExtras cmd) {
- if (mLastAssistStructure != null) {
- AssistStructure structure = mLastAssistStructure.get();
- if (structure != null) {
- structure.clearSendChannel();
+ if (mLastSessionId != cmd.sessionId) {
+ // Clear the existing structures
+ mLastSessionId = cmd.sessionId;
+ for (int i = mLastAssistStructures.size() - 1; i >= 0; i--) {
+ AssistStructure structure = mLastAssistStructures.get(i).get();
+ if (structure != null) {
+ structure.clearSendChannel();
+ }
+ mLastAssistStructures.remove(i);
}
}
Bundle data = new Bundle();
@@ -2819,7 +2829,7 @@ public final class ActivityThread {
if (structure == null) {
structure = new AssistStructure();
}
- mLastAssistStructure = new WeakReference<>(structure);
+ mLastAssistStructures.add(new WeakReference<>(structure));
IActivityManager mgr = ActivityManagerNative.getDefault();
try {
mgr.reportAssistContextExtras(cmd.requestToken, data, structure, content, referrer);
@@ -2905,14 +2915,14 @@ public final class ActivityThread {
private void handleMultiWindowModeChanged(IBinder token, boolean isInMultiWindowMode) {
final ActivityClientRecord r = mActivities.get(token);
if (r != null) {
- r.activity.onMultiWindowModeChanged(isInMultiWindowMode);
+ r.activity.dispatchMultiWindowModeChanged(isInMultiWindowMode);
}
}
private void handlePictureInPictureModeChanged(IBinder token, boolean isInPipMode) {
final ActivityClientRecord r = mActivities.get(token);
if (r != null) {
- r.activity.onPictureInPictureModeChanged(isInPipMode);
+ r.activity.dispatchPictureInPictureModeChanged(isInPipMode);
}
}
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 783c37de1552..c62c1115fe81 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -105,7 +105,7 @@ public class AppOpsManager {
// when adding one of these:
// - increment _NUM_OP
- // - add rows to sOpToSwitch, sOpToString, sOpNames, sOpPerms, sOpDefaultMode
+ // - add rows to sOpToSwitch, sOpToString, sOpNames, sOpToPerms, sOpDefault
// - add descriptive strings to Settings/res/values/arrays.xml
// - add the op to the appropriate template in AppOpsState.OpsTemplate (settings app)
@@ -339,6 +339,43 @@ public class AppOpsManager {
public static final String OPSTR_GET_ACCOUNTS
= "android:get_accounts";
+ private static final int[] RUNTIME_PERMISSIONS_OPS = {
+ // Contacts
+ OP_READ_CONTACTS,
+ OP_WRITE_CONTACTS,
+ OP_GET_ACCOUNTS,
+ // Calendar
+ OP_READ_CALENDAR,
+ OP_WRITE_CALENDAR,
+ // SMS
+ OP_SEND_SMS,
+ OP_RECEIVE_SMS,
+ OP_READ_SMS,
+ OP_RECEIVE_WAP_PUSH,
+ OP_RECEIVE_MMS,
+ OP_READ_CELL_BROADCASTS,
+ // Storage
+ OP_READ_EXTERNAL_STORAGE,
+ OP_WRITE_EXTERNAL_STORAGE,
+ // Location
+ OP_COARSE_LOCATION,
+ OP_FINE_LOCATION,
+ // Phone
+ OP_READ_PHONE_STATE,
+ OP_CALL_PHONE,
+ OP_READ_CALL_LOG,
+ OP_WRITE_CALL_LOG,
+ OP_ADD_VOICEMAIL,
+ OP_USE_SIP,
+ OP_PROCESS_OUTGOING_CALLS,
+ // Microphone
+ OP_RECORD_AUDIO,
+ // Camera
+ OP_CAMERA,
+ // Body sensors
+ OP_BODY_SENSORS
+ };
+
/**
* This maps each operation to the operation that serves as the
* switch to determine whether it is allowed. Generally this is
@@ -922,7 +959,7 @@ public class AppOpsManager {
/**
* Mapping from a permission to the corresponding app op.
*/
- private static HashMap<String, Integer> sPermToOp = new HashMap<>();
+ private static HashMap<String, Integer> sRuntimePermToOp = new HashMap<>();
static {
if (sOpToSwitch.length != _NUM_OP) {
@@ -962,9 +999,9 @@ public class AppOpsManager {
sOpStrToOp.put(sOpToString[i], i);
}
}
- for (int i=0; i<_NUM_OP; i++) {
- if (sOpPerms[i] != null) {
- sPermToOp.put(sOpPerms[i], i);
+ for (int op : RUNTIME_PERMISSIONS_OPS) {
+ if (sOpPerms[op] != null) {
+ sRuntimePermToOp.put(sOpPerms[op], op);
}
}
}
@@ -1016,10 +1053,12 @@ public class AppOpsManager {
/**
* Retrieve the app op code for a permission, or null if there is not one.
+ * This API is intended to be used for mapping runtime permissions to the
+ * corresponding app op.
* @hide
*/
public static int permissionToOpCode(String permission) {
- Integer boxedOpCode = sPermToOp.get(permission);
+ Integer boxedOpCode = sRuntimePermToOp.get(permission);
return boxedOpCode != null ? boxedOpCode : OP_NONE;
}
@@ -1352,12 +1391,14 @@ public class AppOpsManager {
* Gets the app op name associated with a given permission.
* The app op name is one of the public constants defined
* in this class such as {@link #OPSTR_COARSE_LOCATION}.
+ * This API is intended to be used for mapping runtime
+ * permissions to the corresponding app op.
*
* @param permission The permission.
* @return The app op associated with the permission or null.
*/
public static String permissionToOp(String permission) {
- final Integer opCode = sPermToOp.get(permission);
+ final Integer opCode = sRuntimePermToOp.get(permission);
if (opCode == null) {
return null;
}
diff --git a/core/java/android/app/ApplicationThreadNative.java b/core/java/android/app/ApplicationThreadNative.java
index ea86dd0558d6..d6da3f44f4a0 100644
--- a/core/java/android/app/ApplicationThreadNative.java
+++ b/core/java/android/app/ApplicationThreadNative.java
@@ -621,7 +621,8 @@ public abstract class ApplicationThreadNative extends Binder
IBinder activityToken = data.readStrongBinder();
IBinder requestToken = data.readStrongBinder();
int requestType = data.readInt();
- requestAssistContextExtras(activityToken, requestToken, requestType);
+ int sessionId = data.readInt();
+ requestAssistContextExtras(activityToken, requestToken, requestType, sessionId);
reply.writeNoException();
return true;
}
@@ -1377,12 +1378,13 @@ class ApplicationThreadProxy implements IApplicationThread {
@Override
public void requestAssistContextExtras(IBinder activityToken, IBinder requestToken,
- int requestType) throws RemoteException {
+ int requestType, int sessionId) throws RemoteException {
Parcel data = Parcel.obtain();
data.writeInterfaceToken(IApplicationThread.descriptor);
data.writeStrongBinder(activityToken);
data.writeStrongBinder(requestToken);
data.writeInt(requestType);
+ data.writeInt(sessionId);
mRemote.transact(REQUEST_ASSIST_CONTEXT_EXTRAS_TRANSACTION, data, null,
IBinder.FLAG_ONEWAY);
data.recycle();
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 55ce6c2a9804..2fcad0d3ced0 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -331,7 +331,7 @@ public interface IActivityManager extends IInterface {
public void forceStopPackage(final String packageName, int userId) throws RemoteException;
// Note: probably don't want to allow applications access to these.
- public void setLockScreenShown(boolean shown) throws RemoteException;
+ public void setLockScreenShown(boolean showing, boolean occluded) throws RemoteException;
public void unhandledBack() throws RemoteException;
public ParcelFileDescriptor openContentUri(Uri uri) throws RemoteException;
@@ -524,7 +524,7 @@ public interface IActivityManager extends IInterface {
public boolean requestAssistContextExtras(int requestType, IResultReceiver receiver,
Bundle receiverExtras,
- IBinder activityToken, boolean focused) throws RemoteException;
+ IBinder activityToken, boolean focused, boolean newSessionId) throws RemoteException;
public void reportAssistContextExtras(IBinder token, Bundle extras,
AssistStructure structure, AssistContent content, Uri referrer) throws RemoteException;
@@ -546,6 +546,8 @@ public interface IActivityManager extends IInterface {
public void performIdleMaintenance() throws RemoteException;
+ public void sendIdleJobTrigger() throws RemoteException;
+
public IActivityContainer createVirtualActivityContainer(IBinder parentActivityToken,
IActivityContainerCallback callback) throws RemoteException;
@@ -1035,4 +1037,5 @@ public interface IActivityManager extends IInterface {
int SWAP_DOCKED_AND_FULLSCREEN_STACK = IBinder.FIRST_CALL_TRANSACTION + 372;
int NOTIFY_LOCKED_PROFILE = IBinder.FIRST_CALL_TRANSACTION + 373;
int START_CONFIRM_DEVICE_CREDENTIAL_INTENT = IBinder.FIRST_CALL_TRANSACTION + 374;
+ int SEND_IDLE_JOB_TRIGGER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 375;
}
diff --git a/core/java/android/app/IApplicationThread.java b/core/java/android/app/IApplicationThread.java
index a3b263876725..559f69fc2aec 100644
--- a/core/java/android/app/IApplicationThread.java
+++ b/core/java/android/app/IApplicationThread.java
@@ -143,8 +143,8 @@ public interface IApplicationThread extends IInterface {
void dumpGfxInfo(FileDescriptor fd, String[] args) throws RemoteException;
void dumpDbInfo(FileDescriptor fd, String[] args) throws RemoteException;
void unstableProviderDied(IBinder provider) throws RemoteException;
- void requestAssistContextExtras(IBinder activityToken, IBinder requestToken, int requestType)
- throws RemoteException;
+ void requestAssistContextExtras(IBinder activityToken, IBinder requestToken, int requestType,
+ int sessionId) throws RemoteException;
void scheduleTranslucentConversionComplete(IBinder token, boolean timeout)
throws RemoteException;
void scheduleOnNewActivityOptions(IBinder token, ActivityOptions options)
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index e60712aaf359..752dc1e88e15 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -466,11 +466,7 @@ public final class LoadedApk {
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 5a5dcbc0ba2c..ee6b60c371f6 100644
--- a/core/java/android/app/usage/DataUsagePolicy.java
+++ b/core/java/android/app/usage/DataUsagePolicy.java
@@ -29,6 +29,7 @@ import java.util.List;
/**
* 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 9963eab9b983..226aa8f2706d 100644
--- a/core/java/android/app/usage/NetworkStats.java
+++ b/core/java/android/app/usage/NetworkStats.java
@@ -193,14 +193,9 @@ public final class NetworkStats implements AutoCloseable {
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 @@ public final class NetworkStats implements AutoCloseable {
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 @@ public final class NetworkStats implements AutoCloseable {
* 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 2e3aca46f904..4a2811778aac 100644
--- a/core/java/android/app/usage/NetworkStatsManager.java
+++ b/core/java/android/app/usage/NetworkStatsManager.java
@@ -106,7 +106,7 @@ public class NetworkStatsManager {
* 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 class NetworkStatsManager {
*/
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 @@ public class NetworkStatsManager {
}
/**
- * 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 @@ public class NetworkStatsManager {
* {@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 @@ public class NetworkStatsManager {
* {@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 class NetworkStatsManager {
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 @@ public class NetworkStatsManager {
* @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 @@ public class NetworkStatsManager {
* 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 class NetworkStatsManager {
*/
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 @@ public class NetworkStatsManager {
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();
}
}
+ /** @removed */
+ public static abstract class DataUsageCallback {
+ /** @removed */
+ @Deprecated
+ public void onLimitReached() {}
+ }
+
/**
- * Base class for data usage callbacks. Should be extended by applications wanting
- * notifications.
+ * Base class for usage callbacks. Should be extended by applications wanting notifications.
*/
- public static class DataUsageCallback {
+ public static abstract class UsageCallback {
+
/**
- * Called when data usage has reached the given policy threshold.
+ * Called when data usage has reached the given threshold.
*/
- public void onLimitReached() {}
+ public abstract void onThresholdReached(int networkType, String subscriberId);
+ /**
+ * @hide used for internal bookkeeping
+ */
private DataUsageRequest request;
}
@@ -414,18 +429,24 @@ public class NetworkStatsManager {
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 @@ public class NetworkStatsManager {
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/bluetooth/le/ScanFilter.java b/core/java/android/bluetooth/le/ScanFilter.java
index 92a38171a160..17a802d59f4f 100644
--- a/core/java/android/bluetooth/le/ScanFilter.java
+++ b/core/java/android/bluetooth/le/ScanFilter.java
@@ -385,9 +385,13 @@ public final class ScanFilter implements Parcelable {
@Override
public int hashCode() {
- return Objects.hash(mDeviceName, mDeviceAddress, mManufacturerId, mManufacturerData,
- mManufacturerDataMask, mServiceDataUuid, mServiceData, mServiceDataMask,
- mServiceUuid, mServiceUuidMask);
+ return Objects.hash(mDeviceName, mDeviceAddress, mManufacturerId,
+ Arrays.hashCode(mManufacturerData),
+ Arrays.hashCode(mManufacturerDataMask),
+ mServiceDataUuid,
+ Arrays.hashCode(mServiceData),
+ Arrays.hashCode(mServiceDataMask),
+ mServiceUuid, mServiceUuidMask);
}
@Override
@@ -401,10 +405,10 @@ public final class ScanFilter implements Parcelable {
ScanFilter other = (ScanFilter) obj;
return Objects.equals(mDeviceName, other.mDeviceName) &&
Objects.equals(mDeviceAddress, other.mDeviceAddress) &&
- mManufacturerId == other.mManufacturerId &&
+ mManufacturerId == other.mManufacturerId &&
Objects.deepEquals(mManufacturerData, other.mManufacturerData) &&
Objects.deepEquals(mManufacturerDataMask, other.mManufacturerDataMask) &&
- Objects.deepEquals(mServiceDataUuid, other.mServiceDataUuid) &&
+ Objects.equals(mServiceDataUuid, other.mServiceDataUuid) &&
Objects.deepEquals(mServiceData, other.mServiceData) &&
Objects.deepEquals(mServiceDataMask, other.mServiceDataMask) &&
Objects.equals(mServiceUuid, other.mServiceUuid) &&
diff --git a/core/java/android/net/DataUsageRequest.java b/core/java/android/net/DataUsageRequest.java
index 8526584d640d..ac9a5a36681a 100644
--- a/core/java/android/net/DataUsageRequest.java
+++ b/core/java/android/net/DataUsageRequest.java
@@ -20,7 +20,6 @@ import android.net.NetworkTemplate;
import android.os.Parcel;
import android.os.Parcelable;
-import java.util.Arrays;
import java.util.Objects;
/**
@@ -28,56 +27,33 @@ import java.util.Objects;
* {@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 @@ public final class DataUsageRequest implements Parcelable {
@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 @@ public final class DataUsageRequest implements Parcelable {
@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 @@ public final class DataUsageRequest implements Parcelable {
@Override
public String toString() {
return "DataUsageRequest [ requestId=" + requestId
- + ", networkTemplates=" + Arrays.toString(templates)
- + ", uids=" + Arrays.toString(uids)
+ + ", networkTemplate=" + template
+ ", thresholdInBytes=" + thresholdInBytes + " ]";
}
@@ -126,23 +99,13 @@ public final class DataUsageRequest implements Parcelable {
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/INetworkPolicyListener.aidl b/core/java/android/net/INetworkPolicyListener.aidl
index 812f1fe5e563..6523192b735a 100644
--- a/core/java/android/net/INetworkPolicyListener.aidl
+++ b/core/java/android/net/INetworkPolicyListener.aidl
@@ -23,5 +23,6 @@ oneway interface INetworkPolicyListener {
void onMeteredIfacesChanged(in String[] meteredIfaces);
void onRestrictBackgroundChanged(boolean restrictBackground);
void onRestrictBackgroundWhitelistChanged(int uid, boolean whitelisted);
+ void onRestrictPowerChanged(boolean restrictPower);
}
diff --git a/core/java/android/net/INetworkPolicyManager.aidl b/core/java/android/net/INetworkPolicyManager.aidl
index 224ff5b395c7..fc9b8dd5f5bb 100644
--- a/core/java/android/net/INetworkPolicyManager.aidl
+++ b/core/java/android/net/INetworkPolicyManager.aidl
@@ -54,6 +54,7 @@ interface INetworkPolicyManager {
/** Control if background data is restricted system-wide. */
void setRestrictBackground(boolean restrictBackground);
boolean getRestrictBackground();
+ boolean getRestrictPower();
/** Callback used to change internal state on tethering */
void onTetheringChanged(String iface, boolean tethering);
diff --git a/core/java/android/net/INetworkStatsService.aidl b/core/java/android/net/INetworkStatsService.aidl
index 2eea9408f96a..e693009c3377 100644
--- a/core/java/android/net/INetworkStatsService.aidl
+++ b/core/java/android/net/INetworkStatsService.aidl
@@ -61,10 +61,10 @@ interface INetworkStatsService {
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/net/NetworkPolicyManager.java b/core/java/android/net/NetworkPolicyManager.java
index e464a4a31497..51c45e056092 100644
--- a/core/java/android/net/NetworkPolicyManager.java
+++ b/core/java/android/net/NetworkPolicyManager.java
@@ -28,10 +28,10 @@ import android.content.pm.Signature;
import android.os.RemoteException;
import android.os.UserHandle;
import android.text.format.Time;
+import android.util.DebugUtils;
import com.google.android.collect.Sets;
-import java.io.PrintWriter;
import java.util.HashSet;
/**
@@ -49,18 +49,39 @@ public class NetworkPolicyManager {
/** Allow network use (metered or not) in the background in battery save mode. */
public static final int POLICY_ALLOW_BACKGROUND_BATTERY_SAVE = 0x2;
- /* RULE_* are not masks and they must be exclusive */
- public static final int RULE_UNKNOWN = -1;
- /** All network traffic should be allowed. */
- public static final int RULE_ALLOW_ALL = 0;
- /** Reject traffic on metered networks. */
- public static final int RULE_REJECT_METERED = 1;
- /** Reject traffic on all networks. */
- public static final int RULE_REJECT_ALL = 2;
+ /*
+ * Rules defining whether an uid has access to a network given its type (metered / non-metered).
+ *
+ * These rules are bits and can be used in bitmask operations; in particular:
+ * - rule & RULE_MASK_METERED: returns the metered-networks status.
+ * - rule & RULE_MASK_ALL: returns the all-networks status.
+ *
+ * The RULE_xxx_ALL rules applies to all networks (metered or non-metered), but on
+ * metered networks, the RULE_xxx_METERED rules should be checked first. For example,
+ * if the device is on Battery Saver Mode and Data Saver Mode simulatenously, and a uid
+ * is whitelisted for the former but not the latter, its status would be
+ * RULE_REJECT_METERED | RULE_ALLOW_ALL, meaning it could have access to non-metered
+ * networks but not to metered networks.
+ *
+ * See network-policy-restrictions.md for more info.
+ */
+ /** No specific rule was set */
+ public static final int RULE_NONE = 0;
/** Allow traffic on metered networks. */
- public static final int RULE_ALLOW_METERED = 3;
+ public static final int RULE_ALLOW_METERED = 1 << 0;
/** Temporarily allow traffic on metered networks because app is on foreground. */
- public static final int RULE_TEMPORARY_ALLOW_METERED = 4;
+ public static final int RULE_TEMPORARY_ALLOW_METERED = 1 << 1;
+ /** Reject traffic on metered networks. */
+ public static final int RULE_REJECT_METERED = 1 << 2;
+ /** Network traffic should be allowed on all networks (metered or non-metered), although
+ * metered-network restrictions could still apply. */
+ public static final int RULE_ALLOW_ALL = 1 << 5;
+ /** Reject traffic on all networks. */
+ public static final int RULE_REJECT_ALL = 1 << 6;
+ /** Mask used to get the {@code RULE_xxx_METERED} rules */
+ public static final int MASK_METERED_NETWORKS = 0b00001111;
+ /** Mask used to get the {@code RULE_xxx_ALL} rules */
+ public static final int MASK_ALL_NETWORKS = 0b11110000;
public static final int FIREWALL_RULE_DEFAULT = 0;
public static final int FIREWALL_RULE_ALLOW = 1;
@@ -341,4 +362,18 @@ public class NetworkPolicyManager {
// nothing found above; we can apply policy to UID
return true;
}
+
+ /*
+ * @hide
+ */
+ public static String uidRulesToString(int uidRules) {
+ final StringBuilder string = new StringBuilder().append(uidRules).append(" (");
+ if (uidRules == RULE_NONE) {
+ string.append("NONE");
+ } else {
+ string.append(DebugUtils.flagsToString(NetworkPolicyManager.class, "RULE_", uidRules));
+ }
+ string.append(")");
+ return string.toString();
+ }
}
diff --git a/core/java/android/net/network-policy-restrictions.md b/core/java/android/net/network-policy-restrictions.md
new file mode 100644
index 000000000000..fe13f7a5aab9
--- /dev/null
+++ b/core/java/android/net/network-policy-restrictions.md
@@ -0,0 +1,47 @@
+# Data Saver vs Battery Saver
+
+The tables below show whether an app has network access while on background depending on the status of Data Saver mode, Battery Saver mode, and the app's whitelist on those restricted modes.
+
+### How to read the tables
+
+The 2 topmost rows define the Battery Saver mode and whether the app is whitelisted or not for it.
+The 2 leftmost columns define the Data Saver mode and whether the app is whitelisted, not whitelisted, or blacklisted for it.
+The cells define the network status when the app is on background.
+
+More specifically:
+
+* **DS ON**: Data Saver Mode is on
+* **DS OFF**: Data Saver Mode is off
+* **BS ON**: Battery Saver Mode is on
+* **BS OFF**: Battery Saver Mode is off
+* **WL**: app is whitelisted
+* **!WL**: app is not whitelisted
+* **BL**: app is blacklisted
+* **ok**: network access granted while app on background (NetworkInfo's state/detailed state should be `CONNECTED` / `CONNECTED`)
+* **blk**: network access blocked while app on background (NetworkInfo's state/detailed state should be `DISCONNECTED` / `BLOCKED`)
+
+
+## On metered networks
+
+| | | BS | ON | BS | OFF |
+|:-------:|-------|------|-------|------|-------|
+| | | *WL* | *!WL* | *WL* | *!WL* |
+| **DS** | *WL* | ok | blk | ok | ok |
+| **ON** | *!WL* | blk | blk | blk | blk |
+| | *BL* | blk | blk | blk | blk |
+| **DS** | *WL* | blk | ok | ok | ok |
+| **OFF** | *!WL* | blk | ok | ok | ok |
+| | *BL* | blk | blk | blk | blk |
+
+
+## On non-metered networks
+
+| | | BS | ON | BS | OFF |
+|:-------:|-------|------|-------|------|-------|
+| | | *WL* | *!WL* | *WL* | *!WL* |
+| **DS** | *WL* | ok | blk | ok | ok |
+| **ON** | *!WL* | ok | blk | ok | ok |
+| | *BL* | ok | blk | ok | ok |
+| **DS** | *WL* | ok | blk | ok | ok |
+| **OFF** | *!WL* | ok | blk | ok | ok |
+| | *BL* | ok | blk | ok | ok |
diff --git a/core/java/android/os/health/HealthStats.java b/core/java/android/os/health/HealthStats.java
index f0489e244750..90d89c5ced8c 100644
--- a/core/java/android/os/health/HealthStats.java
+++ b/core/java/android/os/health/HealthStats.java
@@ -83,6 +83,10 @@ import java.util.Map;
* returned for UidHealthStats.STATS_PACKAGES, the keys come from the
* {@link android.os.health.PackageHealthStats} class.
*
+ * <p>
+ * The keys that are available are subject to change, depending on what a particular
+ * device or software version is capable of recording. Applications must handle the absence of
+ * data without crashing.
*/
public class HealthStats {
// Header fields
diff --git a/core/java/android/os/health/PackageHealthStats.java b/core/java/android/os/health/PackageHealthStats.java
index 2c30d5f4018c..fb52cb63638c 100644
--- a/core/java/android/os/health/PackageHealthStats.java
+++ b/core/java/android/os/health/PackageHealthStats.java
@@ -37,7 +37,7 @@ public final class PackageHealthStats {
* 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/PidHealthStats.java b/core/java/android/os/health/PidHealthStats.java
index fe3c02cadcc7..0d2a3f14fbb0 100644
--- a/core/java/android/os/health/PidHealthStats.java
+++ b/core/java/android/os/health/PidHealthStats.java
@@ -20,18 +20,56 @@ package android.os.health;
* Keys for {@link HealthStats} returned from
* {@link HealthStats#getStats(int) HealthStats.getStats(int)} with the
* {@link UidHealthStats#STATS_PIDS UidHealthStats.STATS_PIDS} key.
+ * <p>
+ * The values coming from PidHealthStats are a little bit different from
+ * the other HealthStats values. These values are not aggregate or historical
+ * values, but instead live values from when the snapshot is taken. These
+ * tend to be more useful in debugging rogue processes than in gathering
+ * aggregate metrics across the fleet of devices.
*/
public final class PidHealthStats {
private PidHealthStats() {
}
+ /**
+ * Key for a measurement of the current nesting depth of wakelocks for this process.
+ * That is to say, the number of times a nested wakelock has been started but not
+ * stopped. A high number here indicates an improperly paired wakelock acquire/release
+ * combination.
+ * <p>
+ * More details on the individual wake locks is available
+ * by getting the {@link UidHealthStats#TIMERS_WAKELOCKS_FULL},
+ * {@link UidHealthStats#TIMERS_WAKELOCKS_PARTIAL},
+ * {@link UidHealthStats#TIMERS_WAKELOCKS_WINDOW}
+ * and {@link UidHealthStats#TIMERS_WAKELOCKS_DRAW} keys.
+ */
@HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
public static final int MEASUREMENT_WAKE_NESTING_COUNT = HealthKeys.BASE_PID + 1;
+ /**
+ * Key for a measurement of the total number of milleseconds that this process
+ * has held a wake lock.
+ * <p>
+ * More details on the individual wake locks is available
+ * by getting the {@link UidHealthStats#TIMERS_WAKELOCKS_FULL},
+ * {@link UidHealthStats#TIMERS_WAKELOCKS_PARTIAL},
+ * {@link UidHealthStats#TIMERS_WAKELOCKS_WINDOW}
+ * and {@link UidHealthStats#TIMERS_WAKELOCKS_DRAW} keys.
+ */
@HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
public static final int MEASUREMENT_WAKE_SUM_MS = HealthKeys.BASE_PID + 2;
+ /**
+ * Key for a measurement of the time in the {@link android.os.SystemClock#elapsedRealtime}
+ * timebase that a wakelock was first acquired in this process.
+ * <p>
+ * More details on the individual wake locks is available
+ * by getting the {@link UidHealthStats#TIMERS_WAKELOCKS_FULL},
+ * {@link UidHealthStats#TIMERS_WAKELOCKS_PARTIAL},
+ * {@link UidHealthStats#TIMERS_WAKELOCKS_WINDOW}
+ * and {@link UidHealthStats#TIMERS_WAKELOCKS_DRAW} keys.
+ */
@HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
public static final int MEASUREMENT_WAKE_START_MS = HealthKeys.BASE_PID + 3;
diff --git a/core/java/android/os/health/ProcessHealthStats.java b/core/java/android/os/health/ProcessHealthStats.java
index e004ecb27ad5..b3f0dfc50066 100644
--- a/core/java/android/os/health/ProcessHealthStats.java
+++ b/core/java/android/os/health/ProcessHealthStats.java
@@ -26,21 +26,42 @@ public final class ProcessHealthStats {
private ProcessHealthStats() {
}
+ /**
+ * Key for a measurement of number of millseconds the CPU spent running in user space
+ * for this process.
+ */
@HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
public static final int MEASUREMENT_USER_TIME_MS = HealthKeys.BASE_PROCESS + 1;
+ /**
+ * Key for a measurement of number of millseconds the CPU spent running in kernel space
+ * for this process.
+ */
@HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
public static final int MEASUREMENT_SYSTEM_TIME_MS = HealthKeys.BASE_PROCESS + 2;
+ /**
+ * Key for a measurement of the number of times this process was started for any reason.
+ */
@HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
public static final int MEASUREMENT_STARTS_COUNT = HealthKeys.BASE_PROCESS + 3;
+ /**
+ * Key for a measurement of the number of crashes that happened in this process.
+ */
@HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
public static final int MEASUREMENT_CRASHES_COUNT = HealthKeys.BASE_PROCESS + 4;
+ /**
+ * Key for a measurement of the number of ANRs that happened in this process.
+ */
@HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
public static final int MEASUREMENT_ANR_COUNT = HealthKeys.BASE_PROCESS + 5;
+ /**
+ * Key for a measurement of the number of milliseconds this process spent with
+ * an activity in the foreground.
+ */
@HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
public static final int MEASUREMENT_FOREGROUND_MS = HealthKeys.BASE_PROCESS + 6;
diff --git a/core/java/android/os/health/ServiceHealthStats.java b/core/java/android/os/health/ServiceHealthStats.java
index 802ad31894b3..cc48b3eb9e14 100644
--- a/core/java/android/os/health/ServiceHealthStats.java
+++ b/core/java/android/os/health/ServiceHealthStats.java
@@ -26,9 +26,20 @@ public final class ServiceHealthStats {
private ServiceHealthStats() {
}
+ /**
+ * Key for a measurement of the number of times this service was started due to calls to
+ * {@link android.content.Context#startService startService()}, including re-launches
+ * after crashes.
+ */
@HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
public static final int MEASUREMENT_START_SERVICE_COUNT = HealthKeys.BASE_SERVICE + 1;
+ /**
+ * Key for a measurement of the total number of times this service was started
+ * due to calls to {@link android.content.Context#startService startService()}
+ * or {@link android.content.Context#bindService bindService()} including re-launches
+ * after crashes.
+ */
@HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
public static final int MEASUREMENT_LAUNCH_COUNT = HealthKeys.BASE_SERVICE + 2;
diff --git a/core/java/android/os/health/SystemHealthManager.java b/core/java/android/os/health/SystemHealthManager.java
index 520e84e0266a..7c37fa40154f 100644
--- a/core/java/android/os/health/SystemHealthManager.java
+++ b/core/java/android/os/health/SystemHealthManager.java
@@ -27,6 +27,11 @@ import com.android.internal.app.IBatteryStats;
/**
* Provides access to data about how various system resources are used by applications.
* @more
+ * <p>
+ * If you are going to be using this class to log your application's resource usage,
+ * please consider the amount of resources (battery, network, etc) that will be used
+ * by the logging itself. It can be substantial.
+ * <p>
* <b>Battery Usage</b><br>
* The statistics related to power (battery) usage are recorded since the device
* was last unplugged. It is expected that applications schedule more work to do
@@ -66,7 +71,7 @@ public class SystemHealthManager {
* @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/health/TimerStat.java b/core/java/android/os/health/TimerStat.java
index b9d8874e8938..6af1faf25107 100644
--- a/core/java/android/os/health/TimerStat.java
+++ b/core/java/android/os/health/TimerStat.java
@@ -101,14 +101,14 @@ public final class TimerStat implements Parcelable {
}
/**
- * Set the time for this timer.
+ * Set the time for this timer in milliseconds.
*/
public void setTime(long time) {
mTime = time;
}
/**
- * Get the time for this timer.
+ * Get the time for this timer in milliseconds.
*/
public long getTime() {
return mTime;
diff --git a/core/java/android/os/health/UidHealthStats.java b/core/java/android/os/health/UidHealthStats.java
index 337235a38bde..a702cdb6093c 100644
--- a/core/java/android/os/health/UidHealthStats.java
+++ b/core/java/android/os/health/UidHealthStats.java
@@ -74,6 +74,11 @@ public final class UidHealthStats {
@HealthKeys.Constant(type=HealthKeys.TYPE_TIMERS)
public static final int TIMERS_WAKELOCKS_WINDOW = HealthKeys.BASE_UID + 7;
+ /**
+ * Key for a TimerStat for the times a system-defined wakelock was acquired
+ * to allow the application to draw when it otherwise would not be able to
+ * (e.g. on the lock screen or doze screen).
+ */
@HealthKeys.Constant(type=HealthKeys.TYPE_TIMERS)
public static final int TIMERS_WAKELOCKS_DRAW = HealthKeys.BASE_UID + 8;
@@ -125,144 +130,316 @@ public final class UidHealthStats {
@HealthKeys.Constant(type=HealthKeys.TYPE_STATS)
public static final int STATS_PACKAGES = HealthKeys.BASE_UID + 15;
+ /**
+ * Key for a measurement of number of millseconds the wifi controller was
+ * idle but turned on on behalf of this uid.
+ */
@HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
public static final int MEASUREMENT_WIFI_IDLE_MS = HealthKeys.BASE_UID + 16;
+ /**
+ * Key for a measurement of number of millseconds the wifi transmitter was
+ * receiving data for this uid.
+ */
@HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
public static final int MEASUREMENT_WIFI_RX_MS = HealthKeys.BASE_UID + 17;
+ /**
+ * Key for a measurement of number of millseconds the wifi transmitter was
+ * transmitting data for this uid.
+ */
@HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
public static final int MEASUREMENT_WIFI_TX_MS = HealthKeys.BASE_UID + 18;
+ /**
+ * Key for a measurement of the estimated number of mA*ms used by this uid
+ * for wifi, that is to say the number of milliseconds of wifi activity
+ * times the mA current during that period.
+ */
@HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
public static final int MEASUREMENT_WIFI_POWER_MAMS = HealthKeys.BASE_UID + 19;
+ /**
+ * Key for a measurement of number of millseconds the bluetooth controller was
+ * idle but turned on on behalf of this uid.
+ */
@HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
public static final int MEASUREMENT_BLUETOOTH_IDLE_MS = HealthKeys.BASE_UID + 20;
+ /**
+ * Key for a measurement of number of millseconds the bluetooth transmitter was
+ * receiving data for this uid.
+ */
@HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
public static final int MEASUREMENT_BLUETOOTH_RX_MS = HealthKeys.BASE_UID + 21;
+ /**
+ * Key for a measurement of number of millseconds the bluetooth transmitter was
+ * transmitting data for this uid.
+ */
@HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
public static final int MEASUREMENT_BLUETOOTH_TX_MS = HealthKeys.BASE_UID + 22;
+ /**
+ * Key for a measurement of the estimated number of mA*ms used by this uid
+ * for bluetooth, that is to say the number of milliseconds of activity
+ * times the mA current during that period.
+ */
@HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
public static final int MEASUREMENT_BLUETOOTH_POWER_MAMS = HealthKeys.BASE_UID + 23;
+ /**
+ * Key for a measurement of number of millseconds the mobile radio controller was
+ * idle but turned on on behalf of this uid.
+ */
@HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
public static final int MEASUREMENT_MOBILE_IDLE_MS = HealthKeys.BASE_UID + 24;
+ /**
+ * Key for a measurement of number of millseconds the mobile radio transmitter was
+ * receiving data for this uid.
+ */
@HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
public static final int MEASUREMENT_MOBILE_RX_MS = HealthKeys.BASE_UID + 25;
+ /**
+ * Key for a measurement of number of millseconds the mobile radio transmitter was
+ * transmitting data for this uid.
+ */
@HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
public static final int MEASUREMENT_MOBILE_TX_MS = HealthKeys.BASE_UID + 26;
+ /**
+ * Key for a measurement of the estimated number of mA*ms used by this uid
+ * for mobile data, that is to say the number of milliseconds of activity
+ * times the mA current during that period.
+ */
@HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
public static final int MEASUREMENT_MOBILE_POWER_MAMS = HealthKeys.BASE_UID + 27;
+ /**
+ * Key for a measurement of number of millseconds the wifi controller was
+ * active on behalf of this uid.
+ */
@HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
public static final int MEASUREMENT_WIFI_RUNNING_MS = HealthKeys.BASE_UID + 28;
+ /**
+ * Key for a measurement of number of millseconds that this uid held a full wifi lock.
+ */
@HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
public static final int MEASUREMENT_WIFI_FULL_LOCK_MS = HealthKeys.BASE_UID + 29;
+ /**
+ * Key for a timer for the count and duration of wifi scans done by this uid.
+ */
@HealthKeys.Constant(type=HealthKeys.TYPE_TIMER)
public static final int TIMER_WIFI_SCAN = HealthKeys.BASE_UID + 30;
+ /**
+ * Key for a measurement of number of millseconds that this uid was performing
+ * multicast wifi traffic.
+ */
@HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
public static final int MEASUREMENT_WIFI_MULTICAST_MS = HealthKeys.BASE_UID + 31;
+ /**
+ * Key for a timer for the count and duration of audio playback done by this uid.
+ */
@HealthKeys.Constant(type=HealthKeys.TYPE_TIMER)
public static final int TIMER_AUDIO = HealthKeys.BASE_UID + 32;
+ /**
+ * Key for a timer for the count and duration of video playback done by this uid.
+ */
@HealthKeys.Constant(type=HealthKeys.TYPE_TIMER)
public static final int TIMER_VIDEO = HealthKeys.BASE_UID + 33;
+ /**
+ * Key for a timer for the count and duration this uid had the flashlight turned on.
+ */
@HealthKeys.Constant(type=HealthKeys.TYPE_TIMER)
public static final int TIMER_FLASHLIGHT = HealthKeys.BASE_UID + 34;
+ /**
+ * Key for a timer for the count and duration this uid had the camera turned on.
+ */
@HealthKeys.Constant(type=HealthKeys.TYPE_TIMER)
public static final int TIMER_CAMERA = HealthKeys.BASE_UID + 35;
+ /**
+ * Key for a timer for the count and duration of when an activity from this uid
+ * was the foreground activitiy.
+ */
@HealthKeys.Constant(type=HealthKeys.TYPE_TIMER)
public static final int TIMER_FOREGROUND_ACTIVITY = HealthKeys.BASE_UID + 36;
+ /**
+ * Key for a timer for the count and duration of when this uid was doing bluetooth scans.
+ */
@HealthKeys.Constant(type=HealthKeys.TYPE_TIMER)
public static final int TIMER_BLUETOOTH_SCAN = HealthKeys.BASE_UID + 37;
+ /**
+ * Key for a timer for the count and duration of when this uid was in the "top" process state.
+ */
@HealthKeys.Constant(type=HealthKeys.TYPE_TIMER)
public static final int TIMER_PROCESS_STATE_TOP_MS = HealthKeys.BASE_UID + 38;
+ /**
+ * Key for a timer for the count and duration of when this uid was in the "foreground service"
+ * process state.
+ */
@HealthKeys.Constant(type=HealthKeys.TYPE_TIMER)
public static final int TIMER_PROCESS_STATE_FOREGROUND_SERVICE_MS = HealthKeys.BASE_UID + 39;
+ /**
+ * Key for a timer for the count and duration of when this uid was in the "top sleeping"
+ * process state.
+ */
@HealthKeys.Constant(type=HealthKeys.TYPE_TIMER)
public static final int TIMER_PROCESS_STATE_TOP_SLEEPING_MS = HealthKeys.BASE_UID + 40;
+ /**
+ * Key for a timer for the count and duration of when this uid was in the "foreground"
+ * process state.
+ */
@HealthKeys.Constant(type=HealthKeys.TYPE_TIMER)
public static final int TIMER_PROCESS_STATE_FOREGROUND_MS = HealthKeys.BASE_UID + 41;
+ /**
+ * Key for a timer for the count and duration of when this uid was in the "background"
+ * process state.
+ */
@HealthKeys.Constant(type=HealthKeys.TYPE_TIMER)
public static final int TIMER_PROCESS_STATE_BACKGROUND_MS = HealthKeys.BASE_UID + 42;
+ /**
+ * Key for a timer for the count and duration of when this uid was in the "cached" process
+ * state.
+ */
@HealthKeys.Constant(type=HealthKeys.TYPE_TIMER)
public static final int TIMER_PROCESS_STATE_CACHED_MS = HealthKeys.BASE_UID + 43;
+ /**
+ * Key for a timer for the count and duration this uid had the vibrator turned on.
+ */
@HealthKeys.Constant(type=HealthKeys.TYPE_TIMER)
public static final int TIMER_VIBRATOR = HealthKeys.BASE_UID + 44;
+ /**
+ * Key for a measurement of number of software-generated user activity events caused
+ * by the UID. Calls to userActivity() reset the user activity countdown timer and
+ * keep the screen on for the user's preferred screen-on setting.
+ */
@HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
public static final int MEASUREMENT_OTHER_USER_ACTIVITY_COUNT = HealthKeys.BASE_UID + 45;
+ /**
+ * Key for a measurement of number of user activity events due to physical button presses caused
+ * by the UID. Calls to userActivity() reset the user activity countdown timer and
+ * keep the screen on for the user's preferred screen-on setting.
+ */
@HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
public static final int MEASUREMENT_BUTTON_USER_ACTIVITY_COUNT = HealthKeys.BASE_UID + 46;
+ /**
+ * Key for a measurement of number of user activity events due to touch events caused
+ * by the UID. Calls to userActivity() reset the user activity countdown timer and
+ * keep the screen on for the user's preferred screen-on setting.
+ */
@HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
public static final int MEASUREMENT_TOUCH_USER_ACTIVITY_COUNT = HealthKeys.BASE_UID + 47;
+ /**
+ * Key for a measurement of number of bytes received for this uid by the mobile radio.
+ */
@HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
public static final int MEASUREMENT_MOBILE_RX_BYTES = HealthKeys.BASE_UID + 48;
+ /**
+ * Key for a measurement of number of bytes transmitted for this uid by the mobile radio.
+ */
@HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
public static final int MEASUREMENT_MOBILE_TX_BYTES = HealthKeys.BASE_UID + 49;
+ /**
+ * Key for a measurement of number of bytes received for this uid by the wifi radio.
+ */
@HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
public static final int MEASUREMENT_WIFI_RX_BYTES = HealthKeys.BASE_UID + 50;
+ /**
+ * Key for a measurement of number of bytes transmitted for this uid by the wifi radio.
+ */
@HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
public static final int MEASUREMENT_WIFI_TX_BYTES = HealthKeys.BASE_UID + 51;
+ /**
+ * Key for a measurement of number of bytes received for this uid by the bluetooth radio.
+ */
@HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
public static final int MEASUREMENT_BLUETOOTH_RX_BYTES = HealthKeys.BASE_UID + 52;
+ /**
+ * Key for a measurement of number of bytes transmitted for this uid by the bluetooth radio.
+ */
@HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
public static final int MEASUREMENT_BLUETOOTH_TX_BYTES = HealthKeys.BASE_UID + 53;
+ /**
+ * Key for a measurement of number of packets received for this uid by the mobile radio.
+ */
@HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
public static final int MEASUREMENT_MOBILE_RX_PACKETS = HealthKeys.BASE_UID + 54;
+ /**
+ * Key for a measurement of number of packets transmitted for this uid by the mobile radio.
+ */
@HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
public static final int MEASUREMENT_MOBILE_TX_PACKETS = HealthKeys.BASE_UID + 55;
+ /**
+ * Key for a measurement of number of packets received for this uid by the wifi radio.
+ */
@HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
public static final int MEASUREMENT_WIFI_RX_PACKETS = HealthKeys.BASE_UID + 56;
+ /**
+ * Key for a measurement of number of packets transmitted for this uid by the wifi radio.
+ */
@HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
public static final int MEASUREMENT_WIFI_TX_PACKETS = HealthKeys.BASE_UID + 57;
+ /**
+ * Key for a measurement of number of packets received for this uid by the bluetooth radio.
+ */
@HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
public static final int MEASUREMENT_BLUETOOTH_RX_PACKETS = HealthKeys.BASE_UID + 58;
+ /**
+ * Key for a measurement of number of packets transmitted for this uid by the bluetooth radio.
+ */
@HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
public static final int MEASUREMENT_BLUETOOTH_TX_PACKETS = HealthKeys.BASE_UID + 59;
+ /**
+ * Key for a timer for the count and duration the mobile radio was turned on for this uid.
+ */
@HealthKeys.Constant(type=HealthKeys.TYPE_TIMER)
public static final int TIMER_MOBILE_RADIO_ACTIVE = HealthKeys.BASE_UID + 61;
+ /**
+ * Key for a measurement of the number of milliseconds spent by the CPU running user space
+ * code for this uid.
+ */
@HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
public static final int MEASUREMENT_USER_CPU_TIME_MS = HealthKeys.BASE_UID + 62;
+ /**
+ * Key for a measurement of the number of milliseconds spent by the CPU running kernel
+ * code for this uid.
+ */
@HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
public static final int MEASUREMENT_SYSTEM_CPU_TIME_MS = HealthKeys.BASE_UID + 63;
diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java
index 239f2d0c89b2..bb131a0e83e8 100644
--- a/core/java/android/text/StaticLayout.java
+++ b/core/java/android/text/StaticLayout.java
@@ -754,15 +754,21 @@ public class StaticLayout extends Layout {
&& 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 8cabf42dadf8..130b440dfbbd 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -125,6 +125,7 @@ public final class ViewRootImpl implements ViewParent,
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 @@ public final class ViewRootImpl implements ViewParent,
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 @@ public final class ViewRootImpl implements ViewParent,
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/java/android/widget/RadialTimePickerView.java b/core/java/android/widget/RadialTimePickerView.java
index 8c8d38f18875..02ee2df18aaf 100644
--- a/core/java/android/widget/RadialTimePickerView.java
+++ b/core/java/android/widget/RadialTimePickerView.java
@@ -658,6 +658,13 @@ public class RadialTimePickerView extends View {
if (animate) {
animatePicker(hours, ANIM_DURATION_NORMAL);
+ } else {
+ // If we have a pending or running animator, cancel it.
+ if (mHoursToMinutesAnimator != null && mHoursToMinutesAnimator.isStarted()) {
+ mHoursToMinutesAnimator.cancel();
+ mHoursToMinutesAnimator = null;
+ }
+ mHoursToMinutes = hours ? 0.0f : 1.0f;
}
initData();
diff --git a/core/jni/android_hardware_location_ContextHubService.cpp b/core/jni/android_hardware_location_ContextHubService.cpp
index 98d6b247429c..3881d6d9e99f 100644
--- a/core/jni/android_hardware_location_ContextHubService.cpp
+++ b/core/jni/android_hardware_location_ContextHubService.cpp
@@ -319,14 +319,27 @@ static int onMessageReceipt(uint32_t *header, size_t headerLen, char *msg, size_
}
jbyteArray jmsg = env->NewByteArray(msgLen);
+ if (jmsg == nullptr) {
+ ALOGW("Can't allocate %zu byte array", msgLen);
+ return -1;
+ }
jintArray jheader = env->NewIntArray(headerLen);
+ if (jheader == nullptr) {
+ env->DeleteLocalRef(jmsg);
+ ALOGW("Can't allocate %zu int array", headerLen);
+ return -1;
+ }
env->SetByteArrayRegion(jmsg, 0, msgLen, (jbyte *)msg);
env->SetIntArrayRegion(jheader, 0, headerLen, (jint *)header);
- return (env->CallIntMethod(db.jniInfo.jContextHubService,
+ int ret = (env->CallIntMethod(db.jniInfo.jContextHubService,
db.jniInfo.contextHubServiceMsgReceiptCallback,
jheader, jmsg) != 0);
+ env->DeleteLocalRef(jmsg);
+ env->DeleteLocalRef(jheader);
+
+ return ret;
}
int handle_query_apps_response(char *msg, int msgLen, uint32_t hubHandle) {
@@ -529,12 +542,15 @@ static jobject constructJContextHubInfo(JNIEnv *env, const struct context_hub_t
jstrBuf = env->NewStringUTF(hub->name);
env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetName, jstrBuf);
+ env->DeleteLocalRef(jstrBuf);
jstrBuf = env->NewStringUTF(hub->vendor);
env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetVendor, jstrBuf);
+ env->DeleteLocalRef(jstrBuf);
jstrBuf = env->NewStringUTF(hub->toolchain);
env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetToolchain, jstrBuf);
+ env->DeleteLocalRef(jstrBuf);
env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetPlatformVersion, hub->platform_version);
env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetToolchainVersion, hub->toolchain_version);
@@ -555,11 +571,13 @@ static jobject constructJContextHubInfo(JNIEnv *env, const struct context_hub_t
jintBuf = env->NewIntArray(array_length(dummyConnectedSensors));
env->SetIntArrayRegion(jintBuf, 0, hub->num_connected_sensors, dummyConnectedSensors);
env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetSupportedSensors, jintBuf);
+ env->DeleteLocalRef(jintBuf);
// We are not getting the memory regions from the CH Hal - change this when it is available
jmemBuf = env->NewObjectArray(0, db.jniInfo.memoryRegionsClass, nullptr);
// Note the zero size above. We do not need to set any elements
env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetMemoryRegions, jmemBuf);
+ env->DeleteLocalRef(jmemBuf);
return jHub;
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 9725e4f94160..c2ff4ef22278 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -307,7 +307,7 @@
<protected-broadcast android:name="android.intent.action.ACTION_IDLE_MAINTENANCE_START" />
<protected-broadcast android:name="android.intent.action.ACTION_IDLE_MAINTENANCE_END" />
- <protected-broadcast android:name="com.android.server.task.controllers.IdleController.ACTION_TRIGGER_IDLE" />
+ <protected-broadcast android:name="com.android.server.ACTION_TRIGGER_IDLE" />
<protected-broadcast android:name="android.intent.action.HDMI_PLUGGED" />
@@ -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 547d3cafb621..4670dcabe211 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 7fa9f16f9968..2ef61e889813 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 858cf27bdcb1..7590ea9d4b07 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 c32b98c0996f..27aecadfc8e6 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 455632dd0f3b..cf04177b5d1f 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 260992a4a801..33c8f7c67d7a 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 316626d84b9b..29e6dec523b7 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 60671abb85b5..984035d8e608 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 51015f22b568..52ddeb04b74b 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 8ce922eedd5c..3ba6ce1be034 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 c64a93485b07..29818df192e4 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/core/tests/coretests/src/android/net/NetworkPolicyManagerTest.java b/core/tests/coretests/src/android/net/NetworkPolicyManagerTest.java
new file mode 100644
index 000000000000..fc9c9d335467
--- /dev/null
+++ b/core/tests/coretests/src/android/net/NetworkPolicyManagerTest.java
@@ -0,0 +1,107 @@
+/*
+ * 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 android.net;
+
+import static android.net.NetworkPolicyManager.MASK_ALL_NETWORKS;
+import static android.net.NetworkPolicyManager.MASK_METERED_NETWORKS;
+import static android.net.NetworkPolicyManager.RULE_ALLOW_ALL;
+import static android.net.NetworkPolicyManager.RULE_ALLOW_METERED;
+import static android.net.NetworkPolicyManager.RULE_NONE;
+import static android.net.NetworkPolicyManager.RULE_REJECT_ALL;
+import static android.net.NetworkPolicyManager.RULE_REJECT_METERED;
+import static android.net.NetworkPolicyManager.RULE_TEMPORARY_ALLOW_METERED;
+import static android.net.NetworkPolicyManager.uidRulesToString;
+
+import junit.framework.TestCase;
+
+public class NetworkPolicyManagerTest extends TestCase {
+
+ public void testUidRulesToString() {
+ uidRulesToStringTest(RULE_NONE, "0 (NONE)");
+ uidRulesToStringTest(RULE_ALLOW_METERED, "1 (ALLOW_METERED)");
+ uidRulesToStringTest(RULE_TEMPORARY_ALLOW_METERED, "2 (TEMPORARY_ALLOW_METERED)");
+ uidRulesToStringTest(RULE_REJECT_METERED, "4 (REJECT_METERED)");
+ uidRulesToStringTest(RULE_ALLOW_ALL, "32 (ALLOW_ALL)");
+ uidRulesToStringTest(RULE_REJECT_ALL, "64 (REJECT_ALL)");
+
+ uidRulesToStringTest(RULE_ALLOW_METERED | RULE_ALLOW_ALL,
+ "33 (ALLOW_METERED|ALLOW_ALL)");
+ uidRulesToStringTest(RULE_ALLOW_METERED | RULE_REJECT_ALL,
+ "65 (ALLOW_METERED|REJECT_ALL)");
+ uidRulesToStringTest(RULE_TEMPORARY_ALLOW_METERED | RULE_ALLOW_ALL,
+ "34 (TEMPORARY_ALLOW_METERED|ALLOW_ALL)");
+ uidRulesToStringTest(RULE_TEMPORARY_ALLOW_METERED | RULE_REJECT_ALL,
+ "66 (TEMPORARY_ALLOW_METERED|REJECT_ALL)");
+ uidRulesToStringTest(RULE_REJECT_METERED | RULE_ALLOW_ALL,
+ "36 (REJECT_METERED|ALLOW_ALL)");
+ uidRulesToStringTest(RULE_REJECT_METERED | RULE_REJECT_ALL,
+ "68 (REJECT_METERED|REJECT_ALL)");
+ }
+
+ private void uidRulesToStringTest(int uidRules, String expected) {
+ final String actual = uidRulesToString(uidRules);
+ assertEquals("Wrong string for uidRules " + uidRules, expected, actual);
+ }
+
+ public void testMeteredNetworksMask() {
+ assertEquals(RULE_NONE, MASK_METERED_NETWORKS
+ & RULE_NONE);
+
+ assertEquals(RULE_ALLOW_METERED, MASK_METERED_NETWORKS
+ & RULE_ALLOW_METERED);
+ assertEquals(RULE_ALLOW_METERED, MASK_METERED_NETWORKS
+ & (RULE_ALLOW_METERED | RULE_ALLOW_ALL));
+ assertEquals(RULE_ALLOW_METERED, MASK_METERED_NETWORKS
+ & (RULE_ALLOW_METERED | RULE_REJECT_ALL));
+
+ assertEquals(RULE_TEMPORARY_ALLOW_METERED, MASK_METERED_NETWORKS
+ & RULE_TEMPORARY_ALLOW_METERED);
+ assertEquals(RULE_TEMPORARY_ALLOW_METERED, MASK_METERED_NETWORKS
+ & (RULE_TEMPORARY_ALLOW_METERED | RULE_ALLOW_ALL));
+ assertEquals(RULE_TEMPORARY_ALLOW_METERED, MASK_METERED_NETWORKS
+ & (RULE_TEMPORARY_ALLOW_METERED | RULE_REJECT_ALL));
+
+ assertEquals(RULE_REJECT_METERED, MASK_METERED_NETWORKS
+ & RULE_REJECT_METERED);
+ assertEquals(RULE_REJECT_METERED, MASK_METERED_NETWORKS
+ & (RULE_REJECT_METERED | RULE_ALLOW_ALL));
+ assertEquals(RULE_REJECT_METERED, MASK_METERED_NETWORKS
+ & (RULE_REJECT_METERED | RULE_REJECT_ALL));
+ }
+
+ public void testAllNetworksMask() {
+ assertEquals(RULE_NONE, MASK_ALL_NETWORKS
+ & RULE_NONE);
+
+ assertEquals(RULE_ALLOW_ALL, MASK_ALL_NETWORKS
+ & RULE_ALLOW_ALL);
+ assertEquals(RULE_ALLOW_ALL, MASK_ALL_NETWORKS
+ & (RULE_ALLOW_ALL | RULE_ALLOW_METERED));
+ assertEquals(RULE_ALLOW_ALL, MASK_ALL_NETWORKS
+ & (RULE_ALLOW_ALL | RULE_TEMPORARY_ALLOW_METERED));
+ assertEquals(RULE_ALLOW_ALL, MASK_ALL_NETWORKS
+ & (RULE_ALLOW_ALL | RULE_REJECT_METERED));
+
+ assertEquals(RULE_REJECT_ALL, MASK_ALL_NETWORKS
+ & RULE_REJECT_ALL);
+ assertEquals(RULE_REJECT_ALL, MASK_ALL_NETWORKS
+ & (RULE_REJECT_ALL | RULE_ALLOW_METERED));
+ assertEquals(RULE_REJECT_ALL, MASK_ALL_NETWORKS
+ & (RULE_REJECT_ALL | RULE_TEMPORARY_ALLOW_METERED));
+ assertEquals(RULE_REJECT_ALL, MASK_ALL_NETWORKS
+ & (RULE_REJECT_ALL | RULE_REJECT_METERED));
+ }
+}
diff --git a/docs/html/_redirects.yaml b/docs/html/_redirects.yaml
index 07b8ef784f7e..d13a6358a3d9 100644
--- a/docs/html/_redirects.yaml
+++ b/docs/html/_redirects.yaml
@@ -5,24 +5,22 @@ redirects:
to: /about/index.html
- from: /about/versions/api-levels.html
to: /guide/topics/manifest/uses-sdk-element.html#ApiLevels
-- from: /sdk/oem-usb.html
- to: /studio/tools/extras/oem-usb.html
- from: /sdk/installing.html
to: /studio/index.html
- from: /sdk/exploring.html
- to: /studio/guide/index.html
+ to: /studio/intro/update.html
- from: /sdk/installing/adding-packages.html
- to: /studio/tools/help/sdk-manager.html
+ to: /studio/intro/update.html
- from: /sdk/installing/bundle.html
- to: /studio/index.html
+ to: /studio/intro/update.html
- from: /sdk/installing/studio.html
to: /studio/index.html
- from: /sdk/installing/studio-debug.html
- to: /studio/tools/debugging/debugging-studio.html
+ to: /studio/debug/index.html
- from: /tools/debugging/debugging-devtools.html
- to: /studio/tools/debugging/index.html
+ to: /studio/debug/index.html
- from: /tools/debugging/debugging-projects-cmdline.html
- to: /studio/tools/debugging/index.html
+ to: /studio/debug/index.html
- from: /sdk/compatibility-library.html
to: /topic/libraries/support-library/index.html
- from: /tools/extras/support-library.html
@@ -32,11 +30,11 @@ redirects:
- from: /sdk/eclipse-adt.html
to: /studio/tools/sdk/eclipse-adt.html
- from: /sdk/RELEASENOTES.html
- to: /studio/tools/sdk/tools-notes.html
+ to: /studio/releases/sdk-tools.html
- from: /sdk/tools-notes.html
- to: /studio/tools/sdk/tools-notes.html
+ to: /studio/releases/sdk-tools.html
- from: /sdk/adding-components.html
- to: /studio/tools/help/sdk-manager.html
+ to: /studio/intro/update.html
- from: /sdk/ndk/overview.html
to: /ndk/index.html
- from: /sdk/ndk/
@@ -44,15 +42,15 @@ redirects:
- from: /go/vulkan
to: /ndk/guides/graphics/index.html
- from: /tools/sdk/win-usb.html
- to: /studio/guide/run/win-usb.html
+ to: /studio/run/win-usb.html
- from: /tools/sdk/index.html
to: /studio/index.html
- from: /tools/index.html
to: /tools-moved.html
- from: /tools/sdk/installing.html
- to: /studio/sdk/index.html
-- from: /tools/eclipse/installing-adt.html
to: /studio/index.html
+- from: /tools/eclipse/installing-adt.html
+ to: /studio/tools/help/adt.html
- from: /sdk/requirements.html
to: /studio/index.html
- from: /sdk/installing/next.html
@@ -156,7 +154,7 @@ redirects:
- from: /google/play/billing/billing_about.html
to: /google/play/billing/index.html
- from: /guide/developing/tools/
- to: /studio/tools/help/
+ to: /studio/command-line/
- from: /guide/developing/
to: /studio/
- from: /tools/aidl.html
@@ -166,7 +164,7 @@ redirects:
- from: /guide/publishing/publishing.html
to: /distribute/tools/launch-checklist.html
- from: /guide/publishing/
- to: /studio/tools/publishing/publishing_overview.html
+ to: /studio/publish/index.html
- from: /guide/topics/fundamentals.html
to: /guide/components/fundamentals.html
- from: /guide/topics/intents/intents-filters.html
@@ -184,21 +182,21 @@ redirects:
- from: /guide/topics/connectivity/usb/adk.html
to: /adk/index.html
- from: /tools/workflow/publishing/versioning.html
- to: /studio/tools/publishing/versioning.html
+ to: /studio/publish/versioning.html
- from: /tools/workflow/publishing/publishing.html
- to: /studio/tools/publishing/publishing_overview.html
+ to: /studio/publish/index.html
- from: /tools/workflow/publishing_overview.html
- to: /studio/tools/publishing/publishing_overview.html
+ to: /studio/publish/index.html
- from: /tools/workflow/publishing/publishing_overview.html
- to: /studio/tools/publishing/publishing_overview.html
+ to: /studio/publish/index.html
- from: /tools/workflow/app-signing.html
- to: /studio/tools/publishing/app-signing.html
+ to: /studio/publish/app-signing.html
- from: /tools/adk/aoa.html
to: https://source.android.com/tech/accessories/aoap/aoa.html
- from: /tools/adk/aoa2.html
to: https://source.android.com/tech/accessories/aoap/aoa2.html
- from: /tools/eclipse/migrate-adt.html
- to: /studio/installing/migrate.html
+ to: /studio/intro/migrate.html
- from: /guide/topics/usb
to: /guide/topics/connectivity/usb
- from: /guide/appendix/api-levels.html
@@ -216,7 +214,7 @@ redirects:
- from: /guide/appendix/market-filters.html
to: /google/play/filters.html
- from: /guide/topics/testing/
- to: /studio/tools/testing/
+ to: /studio/test/
- from: /guide/topics/graphics/animation.html
to: /guide/topics/graphics/overview.html
- from: /guide/topics/graphics/renderscript/compute.html
@@ -507,8 +505,6 @@ redirects:
to: /distribute/engage/index.html
- from: /essentials/best-practices/...
to: /distribute/googleplay/guide.html
-- from: /tools/index.html
- to: /distribute/essentials/index.html#tools
- from: /users/build-buzz.html
to: /distribute/users/index.html
- from: /users/build-community.html
@@ -800,47 +796,47 @@ redirects:
- from: /2016/03/first-preview-of-android-n-developer.html
to: http://android-developers.blogspot.com/2016/03/first-preview-of-android-n-developer.html
- from: /r/studio-ui/vector-asset-studio.html
- to: /studio/tools/help/vector-asset-studio.html
+ to: /studio/write/vector-asset-studio.html
- from: /r/studio-ui/image-asset-studio.html
- to: /studio/tools/help/image-asset-studio.html
+ to: /studio/write/image-asset-studio.html
- from: /r/studio-ui/project-structure.html
- to: /studio/tools/help/project-mgmt.html
+ to: /studio/projects/index.html
- from: /r/studio-ui/android-monitor.html
- to: /studio/tools/help/android-monitor.html
+ to: /studio/profile/android-monitor.html
- from: /r/studio-ui/am-logcat.html
- to: /studio/tools/help/am-logcat.html
+ to: /studio/debug/am-logcat.html
- from: /r/studio-ui/am-memory.html
- to: /studio/tools/help/am-memory.html
+ to: /studio/profile/am-memory.html
- from: /r/studio-ui/am-cpu.html
- to: /studio/tools/help/am-cpu.html
+ to: /studio/profile/am-cpu.html
- from: /r/studio-ui/am-gpu.html
- to: /studio/tools/help/am-gpu.html
+ to: /studio/profile/am-gpu.html
- from: /r/studio-ui/am-network.html
- to: /studio/tools/help/am-network.html
+ to: /studio/profile/am-network.html
- from: /r/studio-ui/am-hprof.html
- to: /studio/tools/help/am-hprof.html
+ to: /studio/profile/am-hprof.html
- from: /r/studio-ui/am-allocation.html
- to: /studio/tools/help/am-allocation.html
+ to: /studio/profile/am-allocation.html
- from: /r/studio-ui/am-methodtrace.html
- to: /studio/tools/help/am-methodtrace.html
+ to: /studio/profile/am-methodtrace.html
- from: /r/studio-ui/am-sysinfo.html
- to: /studio/tools/help/am-sysinfo.html
+ to: /studio/profile/am-sysinfo.html
- from: /r/studio-ui/am-screenshot.html
- to: /studio/tools/help/am-screenshot.html
+ to: /studio/debug/am-screenshot.html
- from: /r/studio-ui/am-video.html
- to: /studio/tools/help/am-video.html
+ to: /studio/debug/am-video.html
- from: /r/studio-ui/avd-manager.html
- to: /studio/tools/devices/managing-avds.html
+ to: /studio/run/managing-avds.html
- from: /r/studio-ui/rundebugconfig.html
- to: /studio/tools/devices/emulator.html
+ to: /studio/run/emulator.html
- from: /r/studio-ui/devicechooser.html
- to: /studio/tools/devices/emulator.html
+ to: /studio/run/emulator.html
- from: /r/studio-ui/virtualdeviceconfig.html
- to: /studio/tools/devices/emulator.html
+ to: /studio/run/emulator.html
- from: /r/studio-ui/emulator.html
- to: /studio/tools/devices/emulator.html
+ to: /studio/run/emulator.html
- from: /r/studio-ui/instant-run.html
- to: /studio/tools/building/building-studio.html#instant-run
+ to: /studio/run/index.html#instant-run
- from: /reference/org/apache/http/...
to: /about/versions/marshmallow/android-6.0-changes.html#behavior-apache-http-client
- from: /shareables/
@@ -863,49 +859,286 @@ redirects:
- from: /reference/com/google/...
to: https://developers.google.com/android/reference/com/google/...
+
# Files moved during the /studio restructure
- from: /sdk/index.html
to: /studio/index.html
- from: /sdk/win-usb.html
- to: /studio/guide/run/win-usb.html
+ to: /studio/run/win-usb.html
- from: /sdk/terms.html
to: /studio/terms.html
-- from: /sdk/installing/...
- to: /studio/installing/...
-- from: /tools/studio/index.html
- to: /studio/guide/index.html
+- from: /sdk/installing/create-project.html
+ to: /studio/projects/create-project.html
+- from: /sdk/installing/index.html
+ to: /studio/install.html
+- from: /sdk/installing/migrate.html
+ to: /studio/install.html
+- from: /sdk/installing/studio-layout.html
+ to: /studio/write/layout-editor.html
+- from: /tools/building/building-cmdline.html
+ to: /studio/build/building-cmdline.html
+- from: /tools/building/building-studio.html
+ to: /studio/run/index.html
+- from: /tools/building/configuring-gradle.html
+ to: /studio/build/build-variants.html
+- from: /tools/building/manifest-merge.html
+ to: /studio/build/manifest-merge.html
+- from: /tools/building/multidex.html
+ to: /studio/build/multidex.html
+- from: /tools/building/plugin-for-gradle.html
+ to: /studio/build/index.html
+- from: /tools/debugging/annotations.html
+ to: /studio/write/annotations.html
+- from: /tools/debugging/ddms.html
+ to: /studio/profile/ddms.html
+- from: /tools/debugging/debugging-log.html
+ to: /studio/debug/log.html
+- from: /tools/debugging/debugging-memory.html
+ to: /studio/profile/investigate-ram.html
+- from: /tools/debugging/debugging-studio.html
+ to: /studio/debug/index.html
+- from: /tools/debugging/debugging-tracing.html
+ to: /studio/profile/traceview.html
+- from: /tools/debugging/debugging-ui.html
+ to: /studio/profile/optimize-ui.html
+- from: /tools/debugging/improving-w-lint.html
+ to: /studio/write/lint.html
+- from: /tools/debugging/systrace.html
+ to: /studio/profile/systrace.html
+- from: /tools/device.html
+ to: /studio/run/device.html
+- from: /tools/devices/emulator.html
+ to: /studio/run/emulator.html
+- from: /tools/devices/managing-avds.html
+ to: /studio/run/managing-avds.html
+- from: /tools/extras/oem-usb.html
+ to: /studio/run/oem-usb.html
+- from: /tools/help/adb.html
+ to: /studio/command-line/adb.html
+- from: /tools/help/am-allocation.html
+ to: /studio/profile/am-allocation.html
+- from: /tools/help/am-basics.html
+ to: /studio/profile/am-basics.html
+- from: /tools/help/am-cpu.html
+ to: /studio/profile/am-cpu.html
+- from: /tools/help/am-gpu.html
+ to: /studio/profile/am-gpu.html
+- from: /tools/help/am-hprof.html
+ to: /studio/profile/am-hprof.html
+- from: /tools/help/am-logcat.html
+ to: /studio/debug/am-logcat.html
+- from: /tools/help/am-memory.html
+ to: /studio/profile/am-memory.html
+- from: /tools/help/am-methodtrace.html
+ to: /studio/profile/am-methodtrace.html
+- from: /tools/help/am-network.html
+ to: /studio/profile/am-network.html
+- from: /tools/help/am-screenshot.html
+ to: /studio/debug/am-screenshot.html
+- from: /tools/help/am-sysinfo.html
+ to: /studio/profile/am-sysinfo.html
+- from: /tools/help/am-video.html
+ to: /studio/debug/am-video.html
+- from: /tools/help/android-monitor.html
+ to: /studio/profile/android-monitor.html
+- from: /tools/help/app-link-indexing.html
+ to: /studio/write/app-link-indexing.html
+- from: /tools/help/bmgr.html
+ to: /studio/command-line/bmgr.html
+- from: /tools/help/draw9patch.html
+ to: /studio/write/draw9patch.html
+- from: /tools/help/emulator.html
+ to: /studio/run/emulator-commandline.html
+- from: /tools/help/etc1tool.html
+ to: /studio/command-line/etc1tool.html
+- from: /tools/help/gltracer.html
+ to: /studio/profile/gltracer.html
+- from: /tools/help/hierarchy-viewer.html
+ to: /studio/profile/hierarchy-viewer.html
+- from: /tools/help/image-asset-studio.html
+ to: /studio/write/image-asset-studio.html
+- from: /tools/help/index.html
+ to: /studio/command-line/index.html
+- from: /tools/help/jobb.html
+ to: /studio/command-line/jobb.html
+- from: /tools/help/logcat.html
+ to: /studio/command-line/logcat.html
+- from: /tools/help/mksdcard.html
+ to: /studio/command-line/mksdcard.html
+- from: /tools/help/monkey.html
+ to: /studio/test/monkey.html
+- from: /tools/help/MonkeyDevice.html
+ to: /studio/test/monkeyrunner/MonkeyDevice.html
+- from: /tools/help/MonkeyImage.html
+ to: /studio/test/monkeyrunner/MonkeyImage.html
+- from: /tools/help/monkeyrunner_concepts.html
+ to: /studio/test/monkeyrunner/index.html
+- from: /tools/help/MonkeyRunner.html
+ to: /studio/test/monkeyrunner/MonkeyRunner.html
+- from: /tools/help/proguard.html
+ to: /studio/build/shrink-code.html
+- from: /tools/help/sdk-manager.html
+ to: /studio/intro/update.html
+- from: /tools/help/shell.html
+ to: /studio/command-line/shell.html
+- from: /tools/help/sqlite3.html
+ to: /studio/command-line/sqlite3.html
+- from: /tools/help/systrace.html
+ to: /studio/profile/systrace-commandline.html
+- from: /tools/help/theme-editor.html
+ to: /studio/write/theme-editor.html
+- from: /tools/help/traceview.html
+ to: /studio/profile/traceview.html
+- from: /tools/help/translations-editor.html
+ to: /studio/write/translations-editor.html
+- from: /tools/help/uiautomator/Configurator.html
+ to: /studio/test/uiautomator/Configurator.html
+- from: /tools/help/uiautomator/IAutomationSupport.html
+ to: /studio/test/uiautomator/IAutomationSupport.html
+- from: /tools/help/uiautomator/index.html
+ to: /studio/test/uiautomator/index.html
+- from: /tools/help/uiautomator/UiAutomatorTestCase.html
+ to: /studio/test/uiautomator/UiAutomatorTestCase.html
+- from: /tools/help/uiautomator/UiCollection.html
+ to: /studio/test/uiautomator/UiCollection.html
+- from: /tools/help/uiautomator/UiDevice.html
+ to: /studio/test/uiautomator/UiDevice.html
+- from: /tools/help/uiautomator/UiObject.html
+ to: /studio/test/uiautomator/UiObject.html
+- from: /tools/help/uiautomator/UiObjectNotFoundException.html
+ to: /studio/test/uiautomator/UiObjectNotFoundException.html
+- from: /tools/help/uiautomator/UiScrollable.html
+ to: /studio/test/uiautomator/UiScrollable.html
+- from: /tools/help/uiautomator/UiSelector.html
+ to: /studio/test/uiautomator/UiSelector.html
+- from: /tools/help/uiautomator/UiWatcher.html
+ to: /studio/test/uiautomator/UiWatcher.html
+- from: /tools/help/vector-asset-studio.html
+ to: /studio/write/vector-asset-studio.html
+- from: /tools/help/zipalign.html
+ to: /studio/command-line/zipalign.html
+- from: /tools/performance/allocation-tracker/index.html
+ to: /studio/profile/allocation-tracker-walkthru.html
+- from: /tools/performance/batterystats-battery-historian/charts.html
+ to: /studio/profile/battery-historian-charts.html
+- from: /tools/performance/batterystats-battery-historian/index.html
+ to: /studio/profile/battery-historian.html
+- from: /tools/performance/debug-gpu-overdraw/index.html
+ to: /studio/profile/dev-options-overdraw.html
+- from: /tools/performance/heap-viewer/index.html
+ to: /studio/profile/heap-viewer-walkthru.html
+- from: /tools/performance/hierarchy-viewer/index.html
+ to: /studio/profile/hierarchy-viewer-walkthru.html
+- from: /tools/performance/hierarchy-viewer/profiling.html
+ to: /studio/profile/hierarchy-viewer-results-walkthru.html
+- from: /tools/performance/hierarchy-viewer/setup.html
+ to: /studio/profile/hierarchy-viewer-setup.html
+- from: /tools/performance/index.html
+ to: /studio/profile/index.html
+- from: /tools/performance/profile-gpu-rendering/index.html
+ to: /studio/profile/dev-options-rendering.html
+- from: /tools/performance/systrace/index.html
+ to: /studio/profile/systrace-walkthru.html
+- from: /tools/performance/traceview/index.html
+ to: /studio/profile/traceview-walkthru.html
+- from: /tools/projects/index.html
+ to: /studio/projects/index.html
+- from: /tools/projects/templates.html
+ to: /studio/projects/templates.html
+- from: /tools/publishing/app-signing.html
+ to: /studio/publish/app-signing.html
+- from: /tools/publishing/preparing.html
+ to: /studio/publish/preparing.html
+- from: /tools/publishing/publishing_overview.html
+ to: /studio/publish/index.html
+- from: /tools/publishing/versioning.html
+ to: /studio/publish/versioning.html
+- from: /tools/revisions/build-tools.html
+ to: /studio/releases/build-tools.html
+- from: /tools/revisions/gradle-plugin.html
+ to: /studio/releases/gradle-plugin.html
+- from: /tools/revisions/platforms.html
+ to: /studio/releases/platforms.html
+- from: /tools/revisions/studio.html
+ to: /studio/releases/index.html
+- from: /tools/sdk/tools-notes.html
+ to: /studio/releases/sdk-tools.html
+- from: /tools/studio/studio-config.html
+ to: /studio/intro/studio-config.html
+- from: /tools/testing/testing_android.html
+ to: /studio/test/index.html
+- from: /tools/testing/testing_otheride.html
+ to: /studio/test/command-line.html
+
+# Files moved out of studio
- from: /tools/sdk/ndk/...
to: /ndk/index.html
- from: /tools/adk/...
to: /adk/...
# Removed files
+- from: /tools/help/project-mgmt.html
+ to: /studio/projects/index.html
- from: /tools/help/android.html
- to: /studio/tools/projects/index.html
+ to: /studio/projects/index.html
- from: /tools/help/hprof-conv.html
- to: /studio/tools/debugging/debugging-memory.html
+ to: /studio/profile/investigate-ram.html
- from: /tools/studio/code-tools.html
- to: /studio/guide/write/index.html
+ to: /studio/write/index.html
- from: /tools/studio/ui-tools.html
- to: /studio/guide/write/index.html
+ to: /studio/write/index.html
- from: /tools/help/avd-manager.html
- to: /studio/tools/devices/managing-avds.html
+ to: /studio/run/managing-avds.html
- from: /tools/devices/managing-avds-cmdline.html
- to: /studio/tools/devices/managing-avds.html
+ to: /studio/run/managing-avds.html
- from: /tools/projects/projects-cmdline.html
- to: /studio/tools/revisions/studio.html
+ to: /studio/projects/index.html
- from: /tools/help/dmtracedump.html
- to: /studio/tools/debugging/debugging-tracing.html
+ to: /studio/profile/traceview.html
- from: /tools/help/lint.html
- to: /studio/tools/debugging/improving-w-lint.html
+ to: /studio/write/lint.html
- from: /tools/debugging/index.html
- to: /studio/tools/debugging/debugging-studio.html
-- from: /tools/help/project-mgmt.html
- to: /studio/tools/projects/index.html
+ to: /studio/debug/index.html
+- from: /tools/building/index.html
+ to: /studio/build/index.html
+- from: /sdk/installing/studio-build.html
+ to: /studio/build/index.html
+- from: /tools/studio/studio-features.html
+ to: /studio/features.html
+- from: /tools/studio/index.html
+ to: /studio/intro/index.html
+- from: /tools/studio/eclipse-transition-guide.html
+ to: /studio/intro/migrate.html
+- from: /tools/testing/index.html
+ 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
+
-# Handle the rest of the tool pages that moved into /studio
+# Just incase something was missed, go to intro page
- from: /tools/...
- to: /studio/tools/...
+ to: /studio/intro/index.html
+
# Vanity urls
- from: /background_optimizations
diff --git a/docs/html/jd_collections.js b/docs/html/jd_collections.js
index f155521134ae..7ed40c09f088 100644
--- a/docs/html/jd_collections.js
+++ b/docs/html/jd_collections.js
@@ -169,6 +169,22 @@ var RESOURCE_COLLECTIONS = {
"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 18e1f993fcae..9c75c7caa838 100644
--- a/docs/html/jd_extras_en.js
+++ b/docs/html/jd_extras_en.js
@@ -28,6 +28,233 @@ METADATA['en'].extras = METADATA['en'].extras.concat([
/* 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&#47;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 @@ METADATA['en'].collections = {
"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 @@ METADATA['en'].collections = {
"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 @@ METADATA['en'].collections = {
"title": "",
"resources": [
"google/play/expansion-files.html",
- "tools/help/proguard.html"
+ "studio/build/shrink-code.html"
]
},
"distribute/toolsreference/launchchecklist/platform": {
@@ -4567,6 +4794,22 @@ METADATA['en'].collections = {
"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 @@ METADATA['en'].collections = {
"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 @@ METADATA['en'].collections = {
"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 @@ METADATA['en'].collections = {
"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 @@ METADATA['en'].collections = {
"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 @@ METADATA['en'].collections = {
"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 efac54834676..bfea0f7463e2 100644
--- a/docs/html/training/camera/photobasics.jd
+++ b/docs/html/training/camera/photobasics.jd
@@ -175,7 +175,8 @@ attribute:</p>
</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 @@ private File createImageFile() throws IOException {
// 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 @@ private void dispatchTakePictureIntent() {
}
// 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>
+&lt;application&gt;
+ ...
+ &lt;provider
+ android:name="android.support.v4.content.FileProvider"
+ android:authorities="com.example.android.fileprovider"
+ android:exported="false"
+ android:grantUriPermissions="true"&gt;
+ &lt;meta-data
+ android:name="android.support.FILE_PROVIDER_PATHS"
+ android:resource="@xml/file_paths"&gt;&lt;/meta-data&gt;
+ &lt;/provider&gt;
+ ...
+&lt;/application&gt;
+</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>
+&lt;?xml version="1.0" encoding="utf-8"?&gt;
+&lt;paths xmlns:android="http://schemas.android.com/apk/res/android"&gt;
+ &lt;external-path name="my_images" path="Android/data/com.example.package.name/files/Pictures" /&gt;
+&lt;/paths&gt;
+</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 000000000000..ddcfc11bdebf
--- /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 000000000000..bf18c16c6780
--- /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 000000000000..10c1377e47ed
--- /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 &gt; Settings</strong> on Windows/Linux, or
+ <strong>Android Studio &gt; Preferences</strong> on Mac). In the left
+ panel, select <strong>Appearance &amp; Behavior &gt;
+ System Settings &gt; 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 000000000000..3d88f3a67d1a
--- /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 000000000000..dc4adf1771b2
--- /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 000000000000..21a77c2907eb
--- /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 000000000000..ad61b98f134a
--- /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 000000000000..cde76c36117b
--- /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 000000000000..4d542d8a9863
--- /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 000000000000..ff8d5bb0327e
--- /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 000000000000..e7a7547c67b8
--- /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 000000000000..f96bf1f20178
--- /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 000000000000..17df757b6c06
--- /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 000000000000..ff11700a2b2e
--- /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 &gt; Settings</strong> on Windows/Linux, or
+ <strong>Android Studio &gt; Preferences</strong> on Mac). In the left
+ panel, select <strong>Appearance &amp; Behavior &gt; System Settings &gt;
+ 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 &amp; Behavior &gt;
+ System Settings &gt; 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 65ac2e9dd12e..93f554f1699f 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>
- </li>
+ <div class="nav-section-header">
+ <a href="<?cs var:toroot ?>wear/preview/api-overview.html">
+ API Overview
+ </a></div>
- <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>
- </li>
+ <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 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>
</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/downloads.html">
+ Downloads
+ </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>
+ <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"><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>
+ <div class="nav-section-header empty">
+ <a href="<?cs var:toroot ?>wear/preview/license.html">
+ License Agreement
+ </a></div>
</li>
-
</ul>
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index ac2a88a17f0b..1fdc1f575bd4 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -133,7 +133,7 @@ public final class Bitmap implements Parcelable {
nativeSize += getByteCount();
}
NativeAllocationRegistry registry = new NativeAllocationRegistry(
- nativeGetNativeFinalizer(), nativeSize);
+ Bitmap.class.getClassLoader(), nativeGetNativeFinalizer(), nativeSize);
registry.registerNativeAllocation(this, nativeBitmap);
}
diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java
index c65880b2fcce..cb6c92e87172 100644
--- a/graphics/java/android/graphics/Canvas.java
+++ b/graphics/java/android/graphics/Canvas.java
@@ -94,7 +94,7 @@ public class Canvas {
// Use a Holder to allow static initialization of Canvas in the boot image.
private static class NoImagePreloadHolder {
public static final NativeAllocationRegistry sRegistry = new NativeAllocationRegistry(
- getNativeFinalizer(), NATIVE_ALLOCATION_SIZE);
+ Canvas.class.getClassLoader(), getNativeFinalizer(), NATIVE_ALLOCATION_SIZE);
}
// This field is used to finalize the native Canvas properly
diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java
index 0dae7961ff20..daa1d7c6648f 100644
--- a/graphics/java/android/graphics/Paint.java
+++ b/graphics/java/android/graphics/Paint.java
@@ -47,7 +47,7 @@ public class Paint {
// Use a Holder to allow static initialization of Paint in the boot image.
private static class NoImagePreloadHolder {
public static final NativeAllocationRegistry sRegistry = new NativeAllocationRegistry(
- nGetNativeFinalizer(), NATIVE_PAINT_SIZE);
+ Paint.class.getClassLoader(), nGetNativeFinalizer(), NATIVE_PAINT_SIZE);
}
/**
diff --git a/graphics/java/android/graphics/drawable/DrawableContainer.java b/graphics/java/android/graphics/drawable/DrawableContainer.java
index 42f48633eacb..8971004f0f72 100644
--- a/graphics/java/android/graphics/drawable/DrawableContainer.java
+++ b/graphics/java/android/graphics/drawable/DrawableContainer.java
@@ -786,13 +786,19 @@ public class DrawableContainer extends Drawable implements Drawable.Callback {
return mChangingConfigurations | mChildrenChangingConfigurations;
}
+ /**
+ * Adds the drawable to the end of the list of contained drawables.
+ *
+ * @param dr the drawable to add
+ * @return the position of the drawable within the container
+ */
public final int addChild(Drawable dr) {
final int pos = mNumChildren;
-
if (pos >= mDrawables.length) {
growArray(pos, pos+10);
}
+ dr.mutate();
dr.setVisible(false, true);
dr.setCallback(mOwner);
diff --git a/media/java/android/media/AudioRoutesInfo.java b/media/java/android/media/AudioRoutesInfo.java
index 6ae0d46c0d75..83cd797ae356 100644
--- a/media/java/android/media/AudioRoutesInfo.java
+++ b/media/java/android/media/AudioRoutesInfo.java
@@ -54,6 +54,23 @@ public class AudioRoutesInfo implements Parcelable {
}
@Override
+ public String toString() {
+ return getClass().getSimpleName() + "{ type=" + typeToString(mainType)
+ + (TextUtils.isEmpty(bluetoothName) ? "" : ", bluetoothName=" + bluetoothName)
+ + " }";
+ }
+
+ private static String typeToString(int type) {
+ if (type == MAIN_SPEAKER) return "SPEAKER";
+ if ((type & MAIN_HEADSET) != 0) return "HEADSET";
+ if ((type & MAIN_HEADPHONES) != 0) return "HEADPHONES";
+ if ((type & MAIN_DOCK_SPEAKERS) != 0) return "DOCK_SPEAKERS";
+ if ((type & MAIN_HDMI) != 0) return "HDMI";
+ if ((type & MAIN_USB) != 0) return "USB";
+ return Integer.toHexString(type);
+ }
+
+ @Override
public void writeToParcel(Parcel dest, int flags) {
TextUtils.writeToParcel(bluetoothName, dest, flags);
dest.writeInt(mainType);
diff --git a/media/java/android/media/MediaRouter.java b/media/java/android/media/MediaRouter.java
index d8e0d6dca9e6..101facd4909b 100644
--- a/media/java/android/media/MediaRouter.java
+++ b/media/java/android/media/MediaRouter.java
@@ -176,6 +176,7 @@ public class MediaRouter {
}
void updateAudioRoutes(AudioRoutesInfo newRoutes) {
+ Log.v(TAG, "Updating audio routes: " + newRoutes);
if (newRoutes.mainType != mCurAudioRoutesInfo.mainType) {
mCurAudioRoutesInfo.mainType = newRoutes.mainType;
int name;
@@ -905,6 +906,7 @@ public class MediaRouter {
}
static void selectRouteStatic(int types, @NonNull RouteInfo route, boolean explicit) {
+ Log.v(TAG, "Selecting route: " + route);
assert(route != null);
final RouteInfo oldRoute = sStatic.mSelectedRoute;
if (oldRoute == route) return;
@@ -1007,6 +1009,7 @@ public class MediaRouter {
}
static void addRouteStatic(RouteInfo info) {
+ Log.v(TAG, "Adding route: " + info);
final RouteCategory cat = info.getCategory();
if (!sStatic.mCategories.contains(cat)) {
sStatic.mCategories.add(cat);
@@ -1061,6 +1064,7 @@ public class MediaRouter {
}
static void removeRouteStatic(RouteInfo info) {
+ Log.v(TAG, "Removing route: " + info);
if (sStatic.mRoutes.remove(info)) {
final RouteCategory removingCat = info.getCategory();
final int count = sStatic.mRoutes.size();
@@ -1210,6 +1214,7 @@ public class MediaRouter {
}
static void dispatchRouteChanged(RouteInfo info, int oldSupportedTypes) {
+ Log.v(TAG, "Dispatching route change: " + info);
final int newSupportedTypes = info.mSupportedTypes;
for (CallbackInfo cbi : sStatic.mCallbacks) {
// Reconstruct some of the history for callbacks that may not have observed
diff --git a/media/java/android/media/browse/MediaBrowser.java b/media/java/android/media/browse/MediaBrowser.java
index baa6b0fc27ef..79b415f8903d 100644
--- a/media/java/android/media/browse/MediaBrowser.java
+++ b/media/java/android/media/browse/MediaBrowser.java
@@ -476,6 +476,9 @@ public final class MediaBrowser {
// the service will be told when we connect.
if (mState == CONNECT_STATE_CONNECTED) {
try {
+ if (options == null) {
+ mServiceBinder.addSubscriptionDeprecated(parentId, mServiceCallbacks);
+ }
mServiceBinder.addSubscription(parentId, callback.mToken, options,
mServiceCallbacks);
} catch (RemoteException ex) {
@@ -500,6 +503,7 @@ public final class MediaBrowser {
try {
if (callback == null) {
if (mState == CONNECT_STATE_CONNECTED) {
+ mServiceBinder.removeSubscriptionDeprecated(parentId, mServiceCallbacks);
mServiceBinder.removeSubscription(parentId, null, mServiceCallbacks);
}
} else {
@@ -1070,7 +1074,12 @@ public final class MediaBrowser {
}
@Override
- public void onLoadChildren(String parentId, ParceledListSlice list,
+ public void onLoadChildren(String parentId, ParceledListSlice list) {
+ onLoadChildrenWithOptions(parentId, list, null);
+ }
+
+ @Override
+ public void onLoadChildrenWithOptions(String parentId, ParceledListSlice list,
final Bundle options) {
MediaBrowser mediaBrowser = mMediaBrowser.get();
if (mediaBrowser != null) {
diff --git a/media/java/android/media/tv/TvContract.java b/media/java/android/media/tv/TvContract.java
index db7b43abaf3d..3a3460bbca17 100644
--- a/media/java/android/media/tv/TvContract.java
+++ b/media/java/android/media/tv/TvContract.java
@@ -1044,7 +1044,8 @@ public final class TvContract {
* The start time of this TV program, in milliseconds since the epoch.
*
* <p>The value should be equal to or larger than {@link #COLUMN_END_TIME_UTC_MILLIS} of the
- * previous program in the same channel.
+ * previous program in the same channel. In practice, start time will usually be the end
+ * time of the previous program.
*
* <p>Type: INTEGER (long)
*/
@@ -1054,7 +1055,8 @@ public final class TvContract {
* The end time of this TV program, in milliseconds since the epoch.
*
* <p>The value should be equal to or less than {@link #COLUMN_START_TIME_UTC_MILLIS} of the
- * next program in the same channel.
+ * next program in the same channel. In practice, end time will usually be the start time of
+ * the next program.
*
* <p>Type: INTEGER (long)
*/
diff --git a/media/java/android/media/tv/TvInputService.java b/media/java/android/media/tv/TvInputService.java
index 168fcdcbd76d..210e62b37e72 100644
--- a/media/java/android/media/tv/TvInputService.java
+++ b/media/java/android/media/tv/TvInputService.java
@@ -78,6 +78,8 @@ public abstract class TvInputService extends Service {
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 @@ public abstract class TvInputService extends Service {
* 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 @@ public abstract class TvInputService extends Service {
// 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 @@ public abstract class TvInputService extends Service {
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/media/java/android/service/media/IMediaBrowserService.aidl b/media/java/android/service/media/IMediaBrowserService.aidl
index 6b6a56116818..84f41f6c3afe 100644
--- a/media/java/android/service/media/IMediaBrowserService.aidl
+++ b/media/java/android/service/media/IMediaBrowserService.aidl
@@ -17,8 +17,11 @@ oneway interface IMediaBrowserService {
void connect(String pkg, in Bundle rootHints, IMediaBrowserServiceCallbacks callbacks);
void disconnect(IMediaBrowserServiceCallbacks callbacks);
+ void addSubscriptionDeprecated(String uri, IMediaBrowserServiceCallbacks callbacks);
+ void removeSubscriptionDeprecated(String uri, IMediaBrowserServiceCallbacks callbacks);
+
+ void getMediaItem(String uri, in ResultReceiver cb, IMediaBrowserServiceCallbacks callbacks);
void addSubscription(String uri, in IBinder token, in Bundle options,
IMediaBrowserServiceCallbacks callbacks);
void removeSubscription(String uri, in IBinder token, IMediaBrowserServiceCallbacks callbacks);
- void getMediaItem(String uri, in ResultReceiver cb, IMediaBrowserServiceCallbacks callbacks);
}
diff --git a/media/java/android/service/media/IMediaBrowserServiceCallbacks.aidl b/media/java/android/service/media/IMediaBrowserServiceCallbacks.aidl
index dadb025060b7..deeab1a8a28b 100644
--- a/media/java/android/service/media/IMediaBrowserServiceCallbacks.aidl
+++ b/media/java/android/service/media/IMediaBrowserServiceCallbacks.aidl
@@ -22,5 +22,6 @@ oneway interface IMediaBrowserServiceCallbacks {
*/
void onConnect(String root, in MediaSession.Token session, in Bundle extras);
void onConnectFailed();
- void onLoadChildren(String mediaId, in ParceledListSlice list, in Bundle options);
+ void onLoadChildren(String mediaId, in ParceledListSlice list);
+ void onLoadChildrenWithOptions(String mediaId, in ParceledListSlice list, in Bundle options);
}
diff --git a/media/java/android/service/media/MediaBrowserService.java b/media/java/android/service/media/MediaBrowserService.java
index 4b88926ce4d4..7eb91884e8d4 100644
--- a/media/java/android/service/media/MediaBrowserService.java
+++ b/media/java/android/service/media/MediaBrowserService.java
@@ -249,6 +249,11 @@ public abstract class MediaBrowserService extends Service {
}
@Override
+ public void addSubscriptionDeprecated(String id, IMediaBrowserServiceCallbacks callbacks) {
+ // do-nothing
+ }
+
+ @Override
public void addSubscription(final String id, final IBinder token, final Bundle options,
final IMediaBrowserServiceCallbacks callbacks) {
mHandler.post(new Runnable() {
@@ -270,6 +275,11 @@ public abstract class MediaBrowserService extends Service {
}
@Override
+ public void removeSubscriptionDeprecated(String id, IMediaBrowserServiceCallbacks callbacks) {
+ // do-nothing
+ }
+
+ @Override
public void removeSubscription(final String id, final IBinder token,
final IMediaBrowserServiceCallbacks callbacks) {
mHandler.post(new Runnable() {
@@ -632,7 +642,7 @@ public abstract class MediaBrowserService extends Service {
final ParceledListSlice<MediaBrowser.MediaItem> pls =
filteredList == null ? null : new ParceledListSlice<>(filteredList);
try {
- connection.callbacks.onLoadChildren(parentId, pls, options);
+ connection.callbacks.onLoadChildrenWithOptions(parentId, pls, options);
} catch (RemoteException ex) {
// The other side is in the process of crashing.
Log.w(TAG, "Calling onLoadChildren() failed for id=" + parentId
diff --git a/media/jni/android_media_Utils.cpp b/media/jni/android_media_Utils.cpp
index 62685c94453c..359ebad5adbe 100644
--- a/media/jni/android_media_Utils.cpp
+++ b/media/jni/android_media_Utils.cpp
@@ -31,7 +31,7 @@
namespace android {
AssetStream::AssetStream(SkStream* stream)
- : mStream(stream) {
+ : mStream(stream), mPosition(0) {
}
AssetStream::~AssetStream() {
@@ -48,7 +48,7 @@ piex::Error AssetStream::GetData(
// Read bytes.
size_t size = mStream->read((void*)data, length);
- mPosition += size;
+ mPosition = offset + size;
return size == length ? piex::Error::kOk : piex::Error::kFail;
}
diff --git a/packages/DocumentsUI/Android.mk b/packages/DocumentsUI/Android.mk
index 568e200fbd98..9d44a6deb0c8 100644
--- a/packages/DocumentsUI/Android.mk
+++ b/packages/DocumentsUI/Android.mk
@@ -36,7 +36,7 @@ LOCAL_JACK_FLAGS := \
# 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/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java
index 2db8fad714a9..5e7a229fda9d 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java
@@ -170,6 +170,7 @@ public class DirectoryFragment extends Fragment
private RootInfo mRoot;
private DocumentInfo mDocument;
private String mQuery = null;
+ // Save selection found during creation so it can be restored during directory loading.
private Selection mSelection = null;
private boolean mSearchMode = false;
private @Nullable ActionMode mActionMode;
@@ -698,7 +699,7 @@ public class DirectoryFragment extends Fragment
public final boolean onBackPressed() {
if (mSelectionManager.hasSelection()) {
- if (DEBUG) Log.d(TAG, "Clearing selection on back pressed.");
+ if (DEBUG) Log.d(TAG, "Clearing selection on selection manager.");
mSelectionManager.clearSelection();
return true;
}
@@ -1817,6 +1818,7 @@ public class DirectoryFragment extends Fragment
if (mSelection != null) {
mSelectionManager.setItemsSelected(mSelection.toList(), true);
+ mSelection.clear();
}
// Restore any previous instance state
diff --git a/packages/ExtServices/src/android/ext/services/notification/Ranker.java b/packages/ExtServices/src/android/ext/services/notification/Ranker.java
index f3ce35566cc0..d43f07627375 100644
--- a/packages/ExtServices/src/android/ext/services/notification/Ranker.java
+++ b/packages/ExtServices/src/android/ext/services/notification/Ranker.java
@@ -73,13 +73,8 @@ public final class Ranker extends NotificationRankerService {
mUnbundledNotifications.put(sbn.getPackageName(), notificationsForPackage);
if (notificationsForPackage.size() >= AUTOBUNDLE_AT_COUNT) {
- // Autobundle all but the most recently posted (not updated) notification.
- int count = 0;
for (String key : notificationsForPackage) {
- if (count < notificationsForPackage.size() - 1) {
- notificationsToBundle.add(key);
- }
- count++;
+ notificationsToBundle.add(key);
}
}
}
diff --git a/packages/MtpDocumentsProvider/Android.mk b/packages/MtpDocumentsProvider/Android.mk
index 0f945ee8a5e1..c9e7195808d2 100644
--- a/packages/MtpDocumentsProvider/Android.mk
+++ b/packages/MtpDocumentsProvider/Android.mk
@@ -11,7 +11,7 @@ LOCAL_PROGUARD_FLAG_FILES := proguard.flags
# 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/res/values-gl-rES/strings.xml b/packages/SettingsLib/res/values-gl-rES/strings.xml
index 410c7a4cb7d4..13edd04e0783 100644
--- a/packages/SettingsLib/res/values-gl-rES/strings.xml
+++ b/packages/SettingsLib/res/values-gl-rES/strings.xml
@@ -219,7 +219,7 @@
<string name="show_hw_screen_updates_summary" msgid="1115593565980196197">"Iluminar vistas das ventás creadas con GPU"</string>
<string name="show_hw_layers_updates" msgid="5645728765605699821">"Ver actualizacións capas"</string>
<string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Iluminar capas hardware en verde ao actualizarse"</string>
- <string name="debug_hw_overdraw" msgid="2968692419951565417">"Depurar sobredebuxo GPU"</string>
+ <string name="debug_hw_overdraw" msgid="2968692419951565417">"Depurar superposición GPU"</string>
<string name="disable_overlays" msgid="2074488440505934665">"Desact. superposicións HW"</string>
<string name="disable_overlays_summary" msgid="3578941133710758592">"Utilizar sempre GPU para a composición da pantalla"</string>
<string name="simulate_color_space" msgid="6745847141353345872">"Simular o espazo da cor"</string>
diff --git a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
index 9aaddaa66cfa..6d6a4b55bd93 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 @@ public class ApplicationsState {
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/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 31058a98c134..25dc3575d5f8 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -295,6 +295,7 @@
android:theme="@style/ForcedResizableTheme"
android:excludeFromRecents="true"
android:stateNotNeeded="true"
+ android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout"
android:exported="false">
</activity>
diff --git a/packages/SystemUI/res/layout/keyguard_user_switcher.xml b/packages/SystemUI/res/layout/keyguard_user_switcher.xml
index 22834e1ce560..983ba6d5e240 100644
--- a/packages/SystemUI/res/layout/keyguard_user_switcher.xml
+++ b/packages/SystemUI/res/layout/keyguard_user_switcher.xml
@@ -19,14 +19,5 @@
android:visibility="gone"
android:layout_height="match_parent"
android:layout_width="match_parent">
- <com.android.keyguard.AlphaOptimizedLinearLayout
- android:id="@+id/keyguard_user_switcher_inner"
- android:orientation="vertical"
- android:layout_height="wrap_content"
- android:layout_width="wrap_content"
- android:layout_marginTop="@dimen/status_bar_header_height_keyguard"
- android:layout_gravity="end"
- android:gravity="end"
- android:paddingTop="4dp">
- </com.android.keyguard.AlphaOptimizedLinearLayout>
+ <!-- KeyguardUserSwitcher loads keyguard_user_switcher_inner.xml here -->
</view> \ No newline at end of file
diff --git a/packages/SystemUI/res/layout/keyguard_user_switcher_inner.xml b/packages/SystemUI/res/layout/keyguard_user_switcher_inner.xml
new file mode 100644
index 000000000000..4c1042e70c1a
--- /dev/null
+++ b/packages/SystemUI/res/layout/keyguard_user_switcher_inner.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ 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
+ -->
+<com.android.keyguard.AlphaOptimizedLinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/keyguard_user_switcher_inner"
+ android:orientation="vertical"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:layout_marginTop="@dimen/status_bar_header_height_keyguard"
+ android:layout_gravity="end"
+ android:gravity="end"
+ android:paddingTop="4dp">
+</com.android.keyguard.AlphaOptimizedLinearLayout>
diff --git a/packages/SystemUI/res/layout/quick_settings_brightness_dialog.xml b/packages/SystemUI/res/layout/quick_settings_brightness_dialog.xml
index 5fde4f696979..5cbe635f9c91 100644
--- a/packages/SystemUI/res/layout/quick_settings_brightness_dialog.xml
+++ b/packages/SystemUI/res/layout/quick_settings_brightness_dialog.xml
@@ -16,6 +16,7 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:systemui="http://schemas.android.com/apk/res-auto"
android:layout_height="48dp"
+ android:layout_width="match_parent"
android:paddingLeft="16dp"
android:paddingRight="16dp"
style="@style/BrightnessDialogContainer">
diff --git a/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml b/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
index 86119426a3e7..5d629401dff3 100644
--- a/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
+++ b/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
@@ -141,17 +141,13 @@
android:gravity="top"
systemui:datePattern="@string/abbrev_wday_month_day_no_year_alarm" />
- <com.android.systemui.statusbar.AlphaOptimizedButton
+ <com.android.systemui.statusbar.AlphaOptimizedImageView
android:id="@+id/alarm_status_collapsed"
android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:drawablePadding="6dp"
- android:drawableStart="@drawable/ic_access_alarms_small"
- android:textColor="#64ffffff"
- android:textAppearance="@style/TextAppearance.StatusBar.Expanded.Date"
+ android:layout_height="match_parent"
+ android:src="@drawable/ic_access_alarms_small"
android:paddingStart="6dp"
- android:gravity="top"
- android:background="?android:attr/selectableItemBackground"
+ android:gravity="center"
android:visibility="gone" />
</LinearLayout>
@@ -171,7 +167,6 @@
<com.android.systemui.qs.QuickQSPanel
android:id="@+id/quick_qs_panel"
- android:background="#0000"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="28dp"
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 55fa10bc238d..cad7f647e031 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -1542,7 +1542,7 @@ public class KeyguardViewMediator extends SystemUI {
private void updateActivityLockScreenState() {
try {
- ActivityManagerNative.getDefault().setLockScreenShown(mShowing && !mOccluded);
+ ActivityManagerNative.getDefault().setLockScreenShown(mShowing, mOccluded);
} catch (RemoteException e) {
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index afb2195d9f99..a5f3e7700cf8 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -41,6 +41,7 @@ import android.view.WindowManager.LayoutParams;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.systemui.Interpolators;
+import com.android.systemui.Prefs;
import com.android.systemui.R;
import com.android.systemui.recents.events.EventBus;
import com.android.systemui.recents.events.activity.CancelEnterRecentsWindowAnimationEvent;
@@ -69,7 +70,6 @@ import com.android.systemui.recents.events.ui.ShowIncompatibleAppOverlayEvent;
import com.android.systemui.recents.events.ui.StackViewScrolledEvent;
import com.android.systemui.recents.events.ui.UpdateFreeformTaskViewVisibilityEvent;
import com.android.systemui.recents.events.ui.UserInteractionEvent;
-import com.android.systemui.recents.events.ui.dragndrop.DragEndEvent;
import com.android.systemui.recents.events.ui.focus.DismissFocusedTaskViewEvent;
import com.android.systemui.recents.events.ui.focus.FocusNextTaskViewEvent;
import com.android.systemui.recents.events.ui.focus.FocusPreviousTaskViewEvent;
@@ -89,7 +89,7 @@ import java.io.FileDescriptor;
import java.io.PrintWriter;
/**
- * The main Recents activity that is started from AlternateRecentsComponent.
+ * The main Recents activity that is started from RecentsComponent.
*/
public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreDrawListener {
@@ -166,6 +166,13 @@ public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreD
if (action.equals(Intent.ACTION_SCREEN_OFF)) {
// When the screen turns off, dismiss Recents to Home
dismissRecentsToHomeIfVisible(false);
+ } else if (action.equals(Intent.ACTION_TIME_CHANGED)) {
+ // For the time being, if the time changes, then invalidate the
+ // last-stack-active-time, this ensures that we will just show the last N tasks
+ // the next time that Recents loads, but prevents really old tasks from showing
+ // up if the task time is set forward.
+ Prefs.putLong(RecentsActivity.this, Prefs.Key.OVERVIEW_LAST_STACK_TASK_ACTIVE_TIME,
+ 0);
}
}
};
@@ -311,6 +318,7 @@ public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreD
// Register the broadcast receiver to handle messages when the screen is turned off
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_SCREEN_OFF);
+ filter.addAction(Intent.ACTION_TIME_CHANGED);
registerReceiver(mSystemBroadcastReceiver, filter);
getWindow().addPrivateFlags(LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION);
@@ -751,13 +759,6 @@ public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreD
mIgnoreAltTabRelease = true;
}
- public final void onBusEvent(final DragEndEvent event) {
- // Handle the case where we drop onto a dock region
- if (event.dropTarget instanceof TaskStack.DockState) {
- mScrimViews.animateScrimToCurrentNavBarState(false /* hasStackTasks */);
- }
- }
-
public final void onBusEvent(final DockedTopTaskEvent event) {
mRecentsView.getViewTreeObserver().addOnPreDrawListener(mRecentsDrawnEventListener);
mRecentsView.invalidate();
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/ui/dragndrop/DragEndCancelledEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/ui/dragndrop/DragEndCancelledEvent.java
new file mode 100644
index 000000000000..edd799597ea6
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/ui/dragndrop/DragEndCancelledEvent.java
@@ -0,0 +1,39 @@
+/*
+ * 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.recents.events.ui.dragndrop;
+
+import com.android.systemui.recents.events.EventBus;
+import com.android.systemui.recents.model.Task;
+import com.android.systemui.recents.model.TaskStack;
+import com.android.systemui.recents.views.DropTarget;
+import com.android.systemui.recents.views.TaskView;
+
+/**
+ * This event is sent whenever a drag end is cancelled because of an error.
+ */
+public class DragEndCancelledEvent extends EventBus.AnimatedEvent {
+
+ public final TaskStack stack;
+ public final Task task;
+ public final TaskView taskView;
+
+ public DragEndCancelledEvent(TaskStack stack, Task task, TaskView taskView) {
+ this.stack = stack;
+ this.task = task;
+ this.taskView = taskView;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
index 46b2612ee7f0..08b52d94ad20 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
@@ -393,18 +393,19 @@ public class SystemServicesProxy {
}
/** Docks a task to the side of the screen and starts it. */
- public void startTaskInDockedMode(int taskId, int createMode) {
- if (mIam == null) return;
+ public boolean startTaskInDockedMode(int taskId, int createMode) {
+ if (mIam == null) return false;
try {
- // TODO: Determine what animation we want for the incoming task
final ActivityOptions options = ActivityOptions.makeBasic();
options.setDockCreateMode(createMode);
options.setLaunchStackId(DOCKED_STACK_ID);
mIam.startActivityFromRecents(taskId, options.toBundle());
- } catch (RemoteException e) {
+ return true;
+ } catch (RemoteException | IllegalArgumentException e) {
e.printStackTrace();
}
+ return false;
}
/** Docks an already resumed task to the side of the screen. */
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java b/packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java
index f6cc12bebb12..9fb8bd557b90 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java
@@ -226,6 +226,18 @@ public class Utilities {
}
/**
+ * Sets the given {@link View}'s frame from its current translation.
+ */
+ public static void setViewFrameFromTranslation(View v) {
+ RectF taskViewRect = new RectF(v.getLeft(), v.getTop(), v.getRight(), v.getBottom());
+ taskViewRect.offset(v.getTranslationX(), v.getTranslationY());
+ v.setTranslationX(0);
+ v.setTranslationY(0);
+ v.setLeftTopRightBottom((int) taskViewRect.left, (int) taskViewRect.top,
+ (int) taskViewRect.right, (int) taskViewRect.bottom);
+ }
+
+ /**
* Returns a view stub for the given view id.
*/
public static ViewStub findViewStubById(View v, int stubId) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java
index 397909580b0d..251ad71e5d62 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java
@@ -140,39 +140,10 @@ public class RecentsTaskLoadPlan {
lastStackActiveTime = 0;
}
long newLastStackActiveTime = -1;
- long prevLastActiveTime = lastStackActiveTime;
int taskCount = mRawTasks.size();
for (int i = 0; i < taskCount; i++) {
ActivityManager.RecentTaskInfo t = mRawTasks.get(i);
- /*
- * Affiliated tasks are returned in a specific order from ActivityManager but without a
- * lastActiveTime since it hasn't yet been started. However, we later sort the task list
- * by lastActiveTime, which rearranges the tasks. For now, we need to workaround this
- * by updating the lastActiveTime of this task to the lastActiveTime of the task it is
- * affiliated with, in the same order that we encounter it in the original list (just
- * its index in the task group for the task it is affiliated with).
- *
- * If the parent task is not available, then we will use the last active time of the
- * previous task as a base point (since the task itself may not have an active time)
- * for the entire affiliated group.
- */
- if (t.persistentId != t.affiliatedTaskId) {
- Task.TaskKey parentTask = affiliatedTasks.get(t.affiliatedTaskId);
- long parentTaskLastActiveTime = parentTask != null
- ? parentTask.lastActiveTime
- : prevLastActiveTime;
- if (RecentsDebugFlags.Static.EnableAffiliatedTaskGroups) {
- t.lastActiveTime = parentTaskLastActiveTime +
- affiliatedTaskCounts.get(t.affiliatedTaskId, 0) + 1;
- } else {
- if (t.lastActiveTime == 0) {
- t.lastActiveTime = parentTaskLastActiveTime -
- affiliatedTaskCounts.get(t.affiliatedTaskId, 0) - 1;
- }
- }
- }
-
// Compose the task key
Task.TaskKey taskKey = new Task.TaskKey(t.persistentId, t.stackId, t.baseIntent,
t.userId, t.firstActiveTime, t.lastActiveTime);
@@ -180,9 +151,14 @@ public class RecentsTaskLoadPlan {
// This task is only shown in the stack if it statisfies the historical time or min
// number of tasks constraints. Freeform tasks are also always shown.
boolean isFreeformTask = SystemServicesProxy.isFreeformStack(t.stackId);
- boolean isStackTask = isFreeformTask || (!isHistoricalTask(t) ||
- (t.lastActiveTime >= lastStackActiveTime && i >= (taskCount - MIN_NUM_TASKS)));
+ boolean isStackTask = isFreeformTask || !isHistoricalTask(t) ||
+ (t.lastActiveTime >= lastStackActiveTime && i >= (taskCount - MIN_NUM_TASKS));
boolean isLaunchTarget = taskKey.id == runningTaskId;
+
+ // The last stack active time is the baseline for which we show visible tasks. Since
+ // the system will store all the tasks, we don't want to show the tasks prior to the
+ // last visible ones, otherwise, as you dismiss them, the previous tasks may satisfy
+ // the other stack-task constraints.
if (isStackTask && newLastStackActiveTime < 0) {
newLastStackActiveTime = t.lastActiveTime;
}
@@ -211,7 +187,6 @@ public class RecentsTaskLoadPlan {
allTasks.add(task);
affiliatedTaskCounts.put(taskKey.id, affiliatedTaskCounts.get(taskKey.id, 0) + 1);
affiliatedTasks.put(taskKey.id, taskKey);
- prevLastActiveTime = t.lastActiveTime;
}
if (newLastStackActiveTime != -1) {
Prefs.putLong(mContext, Prefs.Key.OVERVIEW_LAST_STACK_TASK_ACTIVE_TIME,
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/Task.java b/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
index c6528a157d7a..86a0315496a1 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
@@ -118,6 +118,11 @@ public class Task {
public TaskKey key;
/**
+ * The temporary sort index in the stack, used when ordering the stack.
+ */
+ public int temporarySortIndexInStack;
+
+ /**
* The group will be computed separately from the initialization of the task
*/
@ViewDebug.ExportedProperty(deepExport=true, prefix="group_")
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/TaskKeyLruCache.java b/packages/SystemUI/src/com/android/systemui/recents/model/TaskKeyLruCache.java
index c63a494963a9..23739a083826 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/TaskKeyLruCache.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/TaskKeyLruCache.java
@@ -76,7 +76,8 @@ public class TaskKeyLruCache<V> {
final V getAndInvalidateIfModified(Task.TaskKey key) {
Task.TaskKey lastKey = mKeys.get(key.id);
if (lastKey != null) {
- if ((lastKey.stackId != key.stackId) || (lastKey.lastActiveTime < key.lastActiveTime)) {
+ if ((lastKey.stackId != key.stackId) ||
+ (lastKey.lastActiveTime != key.lastActiveTime)) {
// The task has updated (been made active since the last time it was put into the
// LRU cache) or the stack id for the task has changed, invalidate that cache item
remove(key);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java b/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
index f42eea335e6f..50e28ca2205d 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
@@ -517,16 +517,8 @@ public class TaskStack {
}
}
- // A comparator that sorts tasks by their last active time
- private Comparator<Task> LAST_ACTIVE_TIME_COMPARATOR = new Comparator<Task>() {
- @Override
- public int compare(Task o1, Task o2) {
- return Long.compare(o1.key.lastActiveTime, o2.key.lastActiveTime);
- }
- };
-
- // A comparator that sorts tasks by their last active time and freeform state
- private Comparator<Task> FREEFORM_LAST_ACTIVE_TIME_COMPARATOR = new Comparator<Task>() {
+ // A comparator that sorts tasks by their freeform state
+ private Comparator<Task> FREEFORM_COMPARATOR = new Comparator<Task>() {
@Override
public int compare(Task o1, Task o2) {
if (o1.isFreeformTask() && !o2.isFreeformTask()) {
@@ -534,7 +526,7 @@ public class TaskStack {
} else if (o2.isFreeformTask() && !o1.isFreeformTask()) {
return -1;
}
- return Long.compare(o1.key.lastActiveTime, o2.key.lastActiveTime);
+ return Long.compare(o1.temporarySortIndexInStack, o2.temporarySortIndexInStack);
}
};
@@ -696,7 +688,10 @@ public class TaskStack {
}
// Sort all the tasks to ensure they are ordered correctly
- Collections.sort(allTasks, FREEFORM_LAST_ACTIVE_TIME_COMPARATOR);
+ for (int i = allTasks.size() - 1; i >= 0; i--) {
+ allTasks.get(i).temporarySortIndexInStack = i;
+ }
+ Collections.sort(allTasks, FREEFORM_COMPARATOR);
mStackTaskList.set(allTasks);
mRawTaskList = allTasks;
@@ -769,12 +764,11 @@ public class TaskStack {
}
/**
- * Computes a set of all the active and historical tasks ordered by their last active time.
+ * Computes a set of all the active and historical tasks.
*/
public ArrayList<Task> computeAllTasksList() {
ArrayList<Task> tasks = new ArrayList<>();
tasks.addAll(mStackTaskList.getTasks());
- Collections.sort(tasks, LAST_ACTIVE_TIME_COMPARATOR);
return tasks;
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvActivity.java b/packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvActivity.java
index 9dc9c4c19e5d..acebf427feab 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvActivity.java
@@ -350,13 +350,6 @@ public class RecentsTvActivity extends Activity implements OnPreDrawListener {
} else {
mRecentsView.getViewTreeObserver().addOnPreDrawListener(this);
}
- if(mTaskStackHorizontalGridView.getStack().getTaskCount() > 1 && !mLaunchedFromHome) {
- // If there are 2 or more tasks, and we are not launching from home
- // set the selected position to the 2nd task to allow for faster app switching
- mTaskStackHorizontalGridView.setSelectedPosition(1);
- } else {
- mTaskStackHorizontalGridView.setSelectedPosition(0);
- }
// If this is a new instance from a configuration change, then we have to manually trigger
// the enter animation state, or if recents was relaunched by AM, without going through
@@ -382,6 +375,7 @@ public class RecentsTvActivity extends Activity implements OnPreDrawListener {
if(mLaunchedFromHome) {
mHomeRecentsEnterExitAnimationHolder.startEnterAnimation(mPipManager.isPipShown());
}
+ mTaskStackViewAdapter.setResetAddedCards(true);
EventBus.getDefault().send(new EnterRecentsWindowAnimationCompletedEvent());
}
@@ -389,12 +383,20 @@ public class RecentsTvActivity extends Activity implements OnPreDrawListener {
public void onResume() {
super.onResume();
mPipRecentsOverlayManager.onRecentsResumed();
+ if(mTaskStackHorizontalGridView.getStack().getTaskCount() > 1 && !mLaunchedFromHome) {
+ // If there are 2 or more tasks, and we are not launching from home
+ // set the selected position to the 2nd task to allow for faster app switching
+ mTaskStackHorizontalGridView.setSelectedPosition(1);
+ } else {
+ mTaskStackHorizontalGridView.setSelectedPosition(0);
+ }
}
@Override
public void onPause() {
super.onPause();
mPipRecentsOverlayManager.onRecentsPaused();
+ mTaskStackViewAdapter.setResetAddedCards(false);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/recents/tv/animations/DismissAnimationsHolder.java b/packages/SystemUI/src/com/android/systemui/recents/tv/animations/DismissAnimationsHolder.java
index 084fc874b7b9..65f5fffc5acc 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/tv/animations/DismissAnimationsHolder.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/tv/animations/DismissAnimationsHolder.java
@@ -18,7 +18,6 @@ package com.android.systemui.recents.tv.animations;
import android.animation.Animator.AnimatorListener;
import android.content.res.Resources;
import android.graphics.drawable.TransitionDrawable;
-import android.util.TypedValue;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
@@ -39,7 +38,7 @@ public class DismissAnimationsHolder {
private TransitionDrawable mDismissDrawable;
private TextView mDismissText;
- private float mDismissUnselectedAlpha;
+ private float mDismissIconNotInDismissStateAlpha;
private long mShortDuration;
private long mLongDuration;
@@ -57,7 +56,7 @@ public class DismissAnimationsHolder {
mDismissStartYDelta = mDismissEnterYDelta * 2;
mShortDuration = res.getInteger(R.integer.dismiss_short_duration);
mLongDuration = res.getInteger(R.integer.dismiss_long_duration);
- mDismissUnselectedAlpha = res.getFloat(R.integer.dismiss_unselected_alpha);
+ mDismissIconNotInDismissStateAlpha = res.getFloat(R.integer.dismiss_unselected_alpha);
}
public void startEnterAnimation() {
@@ -94,7 +93,7 @@ public class DismissAnimationsHolder {
mCardDismissIcon.animate()
.setDuration(mShortDuration)
.setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
- .alpha(mDismissUnselectedAlpha)
+ .alpha(mDismissIconNotInDismissStateAlpha)
.withEndAction(new Runnable() {
@Override
public void run() {
@@ -157,7 +156,7 @@ public class DismissAnimationsHolder {
mInfoField.animate().setListener(null);
mThumbnailView.setAlpha(1.0f);
mThumbnailView.setTranslationY(0);
- mCardDismissIcon.setAlpha(mDismissUnselectedAlpha);
+ mCardDismissIcon.setAlpha(0.0f);
mDismissText.setAlpha(0.0f);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/tv/animations/RecentsRowFocusAnimationHolder.java b/packages/SystemUI/src/com/android/systemui/recents/tv/animations/RecentsRowFocusAnimationHolder.java
index 160835f81bcb..45c15379485b 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/tv/animations/RecentsRowFocusAnimationHolder.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/tv/animations/RecentsRowFocusAnimationHolder.java
@@ -52,7 +52,9 @@ public class RecentsRowFocusAnimationHolder {
mFocusLoseAnimatorSet = new AnimatorSet();
mFocusLoseAnimatorSet.playTogether(
- ObjectAnimator.ofFloat(mView, "alpha", dimAlpha),
+ // Animation doesn't start from the current value (1f) sometimes,
+ // so specify the desired initial value here.
+ ObjectAnimator.ofFloat(mView, "alpha", 1f, dimAlpha),
ObjectAnimator.ofFloat(mTitleView, "alpha", 0f));
mFocusLoseAnimatorSet.setDuration(duration);
mFocusLoseAnimatorSet.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskStackHorizontalViewAdapter.java b/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskStackHorizontalViewAdapter.java
index eb3b02d155eb..ed28ef173f0f 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskStackHorizontalViewAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskStackHorizontalViewAdapter.java
@@ -42,6 +42,7 @@ public class TaskStackHorizontalViewAdapter extends
private static final String TAG = "TaskStackViewAdapter";
private List<Task> mTaskList;
private TaskStackHorizontalGridView mGridView;
+ private boolean mResetAddedCards;
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
private TaskCardView mTaskCardView;
@@ -126,6 +127,13 @@ public class TaskStackHorizontalViewAdapter extends
}
@Override
+ public void onViewAttachedToWindow(ViewHolder holder) {
+ if (mResetAddedCards) {
+ holder.mTaskCardView.reset();
+ }
+ }
+
+ @Override
public void onViewDetachedFromWindow(ViewHolder holder) {
// We only want to reset on view detach if this is the last task being dismissed.
// This is so that we do not reset when shifting to apps etc, as it is not needed.
@@ -171,4 +179,8 @@ public class TaskStackHorizontalViewAdapter extends
mTaskList.add(position, task);
notifyItemInserted(position);
}
+
+ public void setResetAddedCards(boolean reset) {
+ mResetAddedCards = reset;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
index fd27b4f1fc27..a8939100f66d 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -64,6 +64,7 @@ import com.android.systemui.recents.events.ui.DismissAllTaskViewsEvent;
import com.android.systemui.recents.events.ui.DraggingInRecentsEndedEvent;
import com.android.systemui.recents.events.ui.DraggingInRecentsEvent;
import com.android.systemui.recents.events.ui.dragndrop.DragDropTargetChangedEvent;
+import com.android.systemui.recents.events.ui.dragndrop.DragEndCancelledEvent;
import com.android.systemui.recents.events.ui.dragndrop.DragEndEvent;
import com.android.systemui.recents.events.ui.dragndrop.DragStartEvent;
import com.android.systemui.recents.misc.ReferenceCountedTrigger;
@@ -510,45 +511,43 @@ public class RecentsView extends FrameLayout {
// We translated the view but we need to animate it back from the current layout-space
// rect to its final layout-space rect
- int x = (int) event.taskView.getTranslationX();
- int y = (int) event.taskView.getTranslationY();
- Rect taskViewRect = new Rect(event.taskView.getLeft(), event.taskView.getTop(),
- event.taskView.getRight(), event.taskView.getBottom());
- taskViewRect.offset(x, y);
- event.taskView.setTranslationX(0);
- event.taskView.setTranslationY(0);
- event.taskView.setLeftTopRightBottom(taskViewRect.left, taskViewRect.top,
- taskViewRect.right, taskViewRect.bottom);
-
- final OnAnimationStartedListener startedListener = new OnAnimationStartedListener() {
- @Override
- public void onAnimationStarted() {
- EventBus.getDefault().send(new DockedFirstAnimationFrameEvent());
- // Remove the task and don't bother relaying out, as all the tasks will be
- // relaid out when the stack changes on the multiwindow change event
- mTaskStackView.getStack().removeTask(event.task, null,
- true /* fromDockGesture */);
- }
- };
+ Utilities.setViewFrameFromTranslation(event.taskView);
// Dock the task and launch it
SystemServicesProxy ssp = Recents.getSystemServices();
- ssp.startTaskInDockedMode(event.task.key.id, dockState.createMode);
- final Rect taskRect = getTaskRect(event.taskView);
- IAppTransitionAnimationSpecsFuture future = mTransitionHelper.getAppTransitionFuture(
- new AnimationSpecComposer() {
- @Override
- public List<AppTransitionAnimationSpec> composeSpecs() {
- return mTransitionHelper.composeDockAnimationSpec(
- event.taskView, taskRect);
- }
- });
- ssp.overridePendingAppTransitionMultiThumbFuture(future,
- mTransitionHelper.wrapStartedListener(startedListener),
- true /* scaleUp */);
-
- MetricsLogger.action(mContext, MetricsEvent.ACTION_WINDOW_DOCK_DRAG_DROP,
- event.task.getTopComponent().flattenToShortString());
+ if (ssp.startTaskInDockedMode(event.task.key.id, dockState.createMode)) {
+ final OnAnimationStartedListener startedListener =
+ new OnAnimationStartedListener() {
+ @Override
+ public void onAnimationStarted() {
+ EventBus.getDefault().send(new DockedFirstAnimationFrameEvent());
+ // Remove the task and don't bother relaying out, as all the tasks will be
+ // relaid out when the stack changes on the multiwindow change event
+ mTaskStackView.getStack().removeTask(event.task, null,
+ true /* fromDockGesture */);
+ }
+ };
+
+ final Rect taskRect = getTaskRect(event.taskView);
+ IAppTransitionAnimationSpecsFuture future =
+ mTransitionHelper.getAppTransitionFuture(
+ new AnimationSpecComposer() {
+ @Override
+ public List<AppTransitionAnimationSpec> composeSpecs() {
+ return mTransitionHelper.composeDockAnimationSpec(
+ event.taskView, taskRect);
+ }
+ });
+ ssp.overridePendingAppTransitionMultiThumbFuture(future,
+ mTransitionHelper.wrapStartedListener(startedListener),
+ true /* scaleUp */);
+
+ MetricsLogger.action(mContext, MetricsEvent.ACTION_WINDOW_DOCK_DRAG_DROP,
+ event.task.getTopComponent().flattenToShortString());
+ } else {
+ EventBus.getDefault().send(new DragEndCancelledEvent(mStack, event.task,
+ event.taskView));
+ }
} else {
// Animate the overlay alpha back to 0
updateVisibleDockRegions(null, true /* isDefaultDockState */, -1, -1,
@@ -565,6 +564,12 @@ public class RecentsView extends FrameLayout {
}
}
+ public final void onBusEvent(final DragEndCancelledEvent event) {
+ // Animate the overlay alpha back to 0
+ updateVisibleDockRegions(null, true /* isDefaultDockState */, -1, -1,
+ true /* animateAlpha */, false /* animateBounds */);
+ }
+
private Rect getTaskRect(TaskView taskView) {
int[] location = taskView.getLocationOnScreen();
int viewX = location[0];
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/SystemBarScrimViews.java b/packages/SystemUI/src/com/android/systemui/recents/views/SystemBarScrimViews.java
index 995f9f74a2f0..8f784b832e4c 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/SystemBarScrimViews.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/SystemBarScrimViews.java
@@ -28,6 +28,9 @@ import com.android.systemui.recents.events.activity.DismissRecentsToHomeAnimatio
import com.android.systemui.recents.events.activity.EnterRecentsWindowAnimationCompletedEvent;
import com.android.systemui.recents.events.ui.DismissAllTaskViewsEvent;
import com.android.systemui.recents.events.activity.MultiWindowStateChangedEvent;
+import com.android.systemui.recents.events.ui.dragndrop.DragEndCancelledEvent;
+import com.android.systemui.recents.events.ui.dragndrop.DragEndEvent;
+import com.android.systemui.recents.model.TaskStack;
/** Manages the scrims for the various system bars. */
public class SystemBarScrimViews {
@@ -154,10 +157,22 @@ public class SystemBarScrimViews {
animateScrimToCurrentNavBarState(event.stack.getStackTaskCount() > 0);
}
+ public final void onBusEvent(final DragEndEvent event) {
+ // Hide the nav bar scrims once we drop to a dock region
+ if (event.dropTarget instanceof TaskStack.DockState) {
+ animateScrimToCurrentNavBarState(false /* hasStackTasks */);
+ }
+ }
+
+ public final void onBusEvent(final DragEndCancelledEvent event) {
+ // Restore the scrims to the normal state
+ animateScrimToCurrentNavBarState(event.stack.getStackTaskCount() > 0);
+ }
+
/**
* Animates the scrim to match the state of the current nav bar.
*/
- public void animateScrimToCurrentNavBarState(boolean hasStackTasks) {
+ private void animateScrimToCurrentNavBarState(boolean hasStackTasks) {
boolean hasNavBarScrim = isNavBarScrimRequired(hasStackTasks);
if (mHasNavBarScrim != hasNavBarScrim) {
AnimationProps animation = hasNavBarScrim
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
index 773e5875b04f..3d0de1cab1e9 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -79,6 +79,7 @@ import com.android.systemui.recents.events.ui.UpdateFreeformTaskViewVisibilityEv
import com.android.systemui.recents.events.ui.UserInteractionEvent;
import com.android.systemui.recents.events.ui.dragndrop.DragDropTargetChangedEvent;
import com.android.systemui.recents.events.ui.dragndrop.DragEndEvent;
+import com.android.systemui.recents.events.ui.dragndrop.DragEndCancelledEvent;
import com.android.systemui.recents.events.ui.dragndrop.DragStartEvent;
import com.android.systemui.recents.events.ui.dragndrop.DragStartInitializeDropTargetsEvent;
import com.android.systemui.recents.events.ui.focus.DismissFocusedTaskViewEvent;
@@ -640,19 +641,23 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
}
/**
- * @see #relayoutTaskViews(AnimationProps, boolean)
+ * @see #relayoutTaskViews(AnimationProps, ArrayMap<Task, AnimationProps>, boolean)
*/
public void relayoutTaskViews(AnimationProps animation) {
- relayoutTaskViews(animation, false /* ignoreTaskOverrides */);
+ relayoutTaskViews(animation, null /* animationOverrides */,
+ false /* ignoreTaskOverrides */);
}
/**
* Relayout the the visible {@link TaskView}s to their current transforms as specified by the
* {@link TaskStackLayoutAlgorithm} with the given {@param animation}. This call cancels any
* animations that are current running on those task views, and will ensure that the children
- * {@link TaskView}s will match the set of visible tasks in the stack.
+ * {@link TaskView}s will match the set of visible tasks in the stack. If a {@link Task} has
+ * an animation provided in {@param animationOverrides}, that will be used instead.
*/
- private void relayoutTaskViews(AnimationProps animation, boolean ignoreTaskOverrides) {
+ private void relayoutTaskViews(AnimationProps animation,
+ ArrayMap<Task, AnimationProps> animationOverrides,
+ boolean ignoreTaskOverrides) {
// If we had a deferred animation, cancel that
cancelDeferredTaskViewLayoutAnimation();
@@ -665,13 +670,18 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
int taskViewCount = taskViews.size();
for (int i = 0; i < taskViewCount; i++) {
TaskView tv = taskViews.get(i);
- int taskIndex = mStack.indexOfStackTask(tv.getTask());
+ Task task = tv.getTask();
+ int taskIndex = mStack.indexOfStackTask(task);
TaskViewTransform transform = mCurrentTaskTransforms.get(taskIndex);
- if (mIgnoreTasks.contains(tv.getTask().key)) {
+ if (mIgnoreTasks.contains(task.key)) {
continue;
}
+ if (animationOverrides != null && animationOverrides.containsKey(task)) {
+ animation = animationOverrides.get(task);
+ }
+
updateTaskViewToTransform(tv, transform, animation);
}
}
@@ -829,6 +839,18 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
}
}
+ /**
+ * Updates the stack layout to its stable places.
+ */
+ private void updateLayoutToStableBounds() {
+ mWindowRect.set(mStableWindowRect);
+ mStackBounds.set(mStableStackBounds);
+ mLayoutAlgorithm.setSystemInsets(mStableLayoutAlgorithm.mSystemInsets);
+ mLayoutAlgorithm.initialize(mDisplayRect, mWindowRect, mStackBounds,
+ TaskStackLayoutAlgorithm.StackState.getStackStateForStack(mStack));
+ updateLayoutAlgorithm(true /* boundScroll */);
+ }
+
/** Returns the scroller. */
public TaskStackViewScroller getScroller() {
return mStackScroller;
@@ -1820,16 +1842,11 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
} else {
// Restore the pre-drag task stack bounds, but ensure that we don't layout the dragging
// task view, so add it back to the ignore set after updating the layout
- mWindowRect.set(mStableWindowRect);
- mStackBounds.set(mStableStackBounds);
removeIgnoreTask(event.task);
- mLayoutAlgorithm.setSystemInsets(mStableLayoutAlgorithm.mSystemInsets);
- mLayoutAlgorithm.initialize(mDisplayRect, mWindowRect, mStackBounds,
- TaskStackLayoutAlgorithm.StackState.getStackStateForStack(mStack));
- updateLayoutAlgorithm(true /* boundScroll */);
+ updateLayoutToStableBounds();
addIgnoreTask(event.task);
}
- relayoutTaskViews(animation, ignoreTaskOverrides);
+ relayoutTaskViews(animation, null /* animationOverrides */, ignoreTaskOverrides);
}
public final void onBusEvent(final DragEndEvent event) {
@@ -1867,30 +1884,38 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
});
}
- // We translated the view but we need to animate it back from the current layout-space rect
- // to its final layout-space rect
- int x = (int) event.taskView.getTranslationX();
- int y = (int) event.taskView.getTranslationY();
- Rect taskViewRect = new Rect(event.taskView.getLeft(), event.taskView.getTop(),
- event.taskView.getRight(), event.taskView.getBottom());
- taskViewRect.offset(x, y);
- event.taskView.setTranslationX(0);
- event.taskView.setTranslationY(0);
- event.taskView.setLeftTopRightBottom(taskViewRect.left, taskViewRect.top,
- taskViewRect.right, taskViewRect.bottom);
+ // Restore the task, so that relayout will apply to it below
+ removeIgnoreTask(event.task);
- // Animate the non-drag TaskViews back into position
- mLayoutAlgorithm.getStackTransform(event.task, getScroller().getStackScroll(),
- mTmpTransform, null);
- event.getAnimationTrigger().increment();
- relayoutTaskViews(new AnimationProps(DEFAULT_SYNC_STACK_DURATION,
+ // Convert the dragging task view back to its final layout-space rect
+ Utilities.setViewFrameFromTranslation(event.taskView);
+
+ // Animate all the tasks into place
+ ArrayMap<Task, AnimationProps> animationOverrides = new ArrayMap<>();
+ animationOverrides.put(event.task, new AnimationProps(SLOW_SYNC_STACK_DURATION,
+ Interpolators.FAST_OUT_SLOW_IN,
+ event.getAnimationTrigger().decrementOnAnimationEnd()));
+ relayoutTaskViews(new AnimationProps(SLOW_SYNC_STACK_DURATION,
Interpolators.FAST_OUT_SLOW_IN));
+ event.getAnimationTrigger().increment();
+ }
- // Animate the drag TaskView back into position
- updateTaskViewToTransform(event.taskView, mTmpTransform,
- new AnimationProps(DEFAULT_SYNC_STACK_DURATION, Interpolators.FAST_OUT_SLOW_IN,
- event.getAnimationTrigger().decrementOnAnimationEnd()));
+ public final void onBusEvent(final DragEndCancelledEvent event) {
+ // Restore the pre-drag task stack bounds, including the dragging task view
removeIgnoreTask(event.task);
+ updateLayoutToStableBounds();
+
+ // Convert the dragging task view back to its final layout-space rect
+ Utilities.setViewFrameFromTranslation(event.taskView);
+
+ // Animate all the tasks into place
+ ArrayMap<Task, AnimationProps> animationOverrides = new ArrayMap<>();
+ animationOverrides.put(event.task, new AnimationProps(SLOW_SYNC_STACK_DURATION,
+ Interpolators.FAST_OUT_SLOW_IN,
+ event.getAnimationTrigger().decrementOnAnimationEnd()));
+ relayoutTaskViews(new AnimationProps(SLOW_SYNC_STACK_DURATION,
+ Interpolators.FAST_OUT_SLOW_IN));
+ event.getAnimationTrigger().increment();
}
public final void onBusEvent(IterateRecentsEvent event) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
index c1e7e0403c88..612c41d07a04 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
@@ -49,6 +49,7 @@ import com.android.systemui.recents.events.EventBus;
import com.android.systemui.recents.events.activity.LaunchTaskEvent;
import com.android.systemui.recents.events.ui.DismissTaskViewEvent;
import com.android.systemui.recents.events.ui.TaskViewDismissedEvent;
+import com.android.systemui.recents.events.ui.dragndrop.DragEndCancelledEvent;
import com.android.systemui.recents.events.ui.dragndrop.DragEndEvent;
import com.android.systemui.recents.events.ui.dragndrop.DragStartEvent;
import com.android.systemui.recents.misc.ReferenceCountedTrigger;
@@ -695,15 +696,18 @@ public class TaskView extends FixedSizeFrameLayout implements Task.TaskCallbacks
public final void onBusEvent(DragEndEvent event) {
if (!(event.dropTarget instanceof TaskStack.DockState)) {
- event.addPostAnimationCallback(new Runnable() {
- @Override
- public void run() {
- // Animate the drag view back from where it is, to the view location, then after
- // it returns, update the clip state
- setClipViewInStack(true);
- }
+ event.addPostAnimationCallback(() -> {
+ // Reset the clip state for the drag view after the end animation completes
+ setClipViewInStack(true);
});
}
EventBus.getDefault().unregister(this);
}
+
+ public final void onBusEvent(DragEndCancelledEvent event) {
+ // Reset the clip state for the drag view after the cancel animation completes
+ event.addPostAnimationCallback(() -> {
+ setClipViewInStack(true);
+ });
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index eec20706ea68..dc5957d70f78 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -92,8 +92,8 @@ import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.statusbar.StatusBarIcon;
import com.android.internal.widget.LockPatternUtils;
-import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardHostView.OnDismissAction;
+import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.DejankUtils;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
@@ -2184,9 +2184,8 @@ public abstract class BaseStatusBar extends SystemUI implements
== 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);
@@ -2194,7 +2193,7 @@ public abstract class BaseStatusBar extends SystemUI implements
} else {
boolean wasGone = entry.row.getVisibility() == View.GONE;
entry.row.setVisibility(View.VISIBLE);
- if (!childNotification) {
+ if (!childNotification && !entry.row.isRemoved()) {
if (wasGone) {
// notify the scroller of a child addition
mStackScroller.generateAddAnimation(entry.row,
@@ -2214,7 +2213,7 @@ public abstract class BaseStatusBar extends SystemUI implements
mStackScroller.getChildCount() - 3);
}
- private boolean shouldShowOnKeyguard(StatusBarNotification sbn) {
+ public boolean shouldShowOnKeyguard(StatusBarNotification sbn) {
return mShowLockscreenNotifications && !mNotificationData.isAmbient(sbn.getKey());
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
index 34c9c0de4459..5a8d4b357719 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 @@ public class NotificationContentView extends FrameLayout {
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 @@ public class NotificationContentView extends FrameLayout {
} 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)
@@ -706,7 +742,7 @@ public class NotificationContentView extends FrameLayout {
}
} else {
if (noExpandedChild || (viewHeight <= mContractedChild.getHeight()
- && (!mIsChildInGroup
+ && (!mIsChildInGroup || isGroupExpanded()
|| !mContainingNotification.isExpanded(true /* allowOnKeyguard */)))) {
return VISIBLE_TYPE_CONTRACTED;
} else {
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 000000000000..c0373bef0f5a
--- /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 889bd5cac7a5..7ca2df99d76e 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 @@ public class NotificationTemplateViewWrapper extends NotificationHeaderViewWrapp
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 @@ public class NotificationTemplateViewWrapper extends NotificationHeaderViewWrapp
// It's still a viewstub
mProgressBar = null;
}
+ mActionsContainer = mView.findViewById(com.android.internal.R.id.actions_container);
}
@Override
@@ -225,4 +230,21 @@ public class NotificationTemplateViewWrapper extends NotificationHeaderViewWrapp
(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 7a0df1f54c64..22519e6e4de3 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 abstract class NotificationViewWrapper implements TransformableView {
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 8207215ec4a9..4e643f0fcae1 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 @@ public class TransformState {
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 @@ public class TransformState {
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/KeyguardStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
index 74bd096aaff3..e08b945493c9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
@@ -85,6 +85,11 @@ public class KeyguardStatusBarView extends RelativeLayout
com.android.internal.R.dimen.text_size_small_material));
mBatteryLevel.setTextSize(TypedValue.COMPLEX_UNIT_PX,
getResources().getDimensionPixelSize(R.dimen.battery_level_text_size));
+
+ MarginLayoutParams lp = (MarginLayoutParams) mMultiUserAvatar.getLayoutParams();
+ lp.width = lp.height = getResources().getDimensionPixelSize(
+ R.dimen.multi_user_avatar_keyguard_size);
+ mMultiUserAvatar.setLayoutParams(lp);
}
private void loadDimens() {
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 ec45d604b829..4ec36f608111 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 @@ public class NavigationBarInflaterView extends FrameLayout implements TunerServi
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 @@ public class NavigationBarInflaterView extends FrameLayout implements TunerServi
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 @@ public class NavigationBarInflaterView extends FrameLayout implements TunerServi
}
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;
}
@@ -282,6 +295,12 @@ public class NavigationBarInflaterView extends FrameLayout implements TunerServi
final int indexOfKey = mButtonDispatchers.indexOfKey(v.getId());
if (indexOfKey >= 0) {
mButtonDispatchers.valueAt(indexOfKey).addView(v);
+ } else if (v instanceof ViewGroup) {
+ final ViewGroup viewGroup = (ViewGroup)v;
+ final int N = viewGroup.getChildCount();
+ for (int i = 0; i < N; i++) {
+ addToDispatchers(viewGroup.getChildAt(i));
+ }
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java
index a51ee4df7ec3..d2326d2c2d7f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java
@@ -24,9 +24,13 @@ import com.android.systemui.statusbar.NotificationData;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.policy.HeadsUpManager;
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
+import java.util.Map;
import java.util.Objects;
/**
@@ -69,6 +73,7 @@ public class NotificationGroupManager implements HeadsUpManager.OnHeadsUpChanged
public void onEntryRemoved(NotificationData.Entry removed) {
onEntryRemovedInternal(removed, removed.notification);
+ mIsolatedEntries.remove(removed.key);
}
/**
@@ -119,11 +124,22 @@ public class NotificationGroupManager implements HeadsUpManager.OnHeadsUpChanged
group.expanded = added.row.areChildrenExpanded();
updateSuppression(group);
if (!group.children.isEmpty()) {
+ HashSet<NotificationData.Entry> childrenCopy =
+ (HashSet<NotificationData.Entry>) group.children.clone();
+ for (NotificationData.Entry child : childrenCopy) {
+ onEntryBecomingChild(child);
+ }
mListener.onGroupCreatedFromChildren(group);
}
}
}
+ private void onEntryBecomingChild(NotificationData.Entry entry) {
+ if (entry.row.isHeadsUp()) {
+ onHeadsUpStateChanged(entry, true);
+ }
+ }
+
public void onEntryBundlingUpdated(final NotificationData.Entry updated,
final String overrideGroupKey) {
final StatusBarNotification oldSbn = updated.notification.clone();
@@ -188,6 +204,8 @@ public class NotificationGroupManager implements HeadsUpManager.OnHeadsUpChanged
updateSuppression(mGroupMap.get(oldKey));
updateSuppression(mGroupMap.get(newKey));
}
+ } else if (!isGroupChild(oldNotification) && isGroupChild(entry.notification)) {
+ onEntryBecomingChild(entry);
}
}
@@ -222,7 +240,12 @@ public class NotificationGroupManager implements HeadsUpManager.OnHeadsUpChanged
}
public void collapseAllGroups() {
- for (NotificationGroup group : mGroupMap.values()) {
+ // Because notifications can become isolated when the group becomes suppressed it can
+ // lead to concurrent modifications while looping. We need to make a copy.
+ ArrayList<NotificationGroup> groupCopy = new ArrayList<>(mGroupMap.values());
+ int size = groupCopy.size();
+ for (int i = 0; i < size; i++) {
+ NotificationGroup group = groupCopy.get(i);
if (group.expanded) {
setGroupExpanded(group, false);
}
@@ -354,7 +377,6 @@ public class NotificationGroupManager implements HeadsUpManager.OnHeadsUpChanged
mListener.onGroupsChanged();
} else {
handleSuppressedSummaryHeadsUpped(entry);
-
}
} else {
if (mIsolatedEntries.containsKey(sbn.getKey())) {
@@ -413,6 +435,19 @@ public class NotificationGroupManager implements HeadsUpManager.OnHeadsUpChanged
mHeadsUpManager = headsUpManager;
}
+ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ pw.println("GroupManager state:");
+ pw.println(" number of groups: " + mGroupMap.size());
+ for (Map.Entry<String, NotificationGroup> entry : mGroupMap.entrySet()) {
+ pw.println("\n key: " + entry.getKey()); pw.println(entry.getValue());
+ }
+ pw.println("\n isolated entries: " + mIsolatedEntries.size());
+ for (Map.Entry<String, StatusBarNotification> entry : mIsolatedEntries.entrySet()) {
+ pw.print(" "); pw.print(entry.getKey());
+ pw.print(", "); pw.println(entry.getValue());
+ }
+ }
+
public static class NotificationGroup {
public final HashSet<NotificationData.Entry> children = new HashSet<>();
public NotificationData.Entry summary;
@@ -421,6 +456,16 @@ public class NotificationGroupManager implements HeadsUpManager.OnHeadsUpChanged
* Is this notification group suppressed, i.e its summary is hidden
*/
public boolean suppressed;
+
+ @Override
+ public String toString() {
+ String result = " summary:\n " + summary.notification;
+ result += "\n children size: " + children.size();
+ for (NotificationData.Entry child : children) {
+ result += "\n " + child.notification;
+ }
+ return result;
+ }
}
public interface OnGroupChangeListener {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index 7e2fa2da94ce..5256e4f6d184 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -418,11 +418,18 @@ public class NotificationPanelView extends PanelView implements
if (!(child instanceof ExpandableNotificationRow)) {
continue;
}
+ ExpandableNotificationRow row = (ExpandableNotificationRow) child;
boolean suppressedSummary = mGroupManager.isSummaryOfSuppressedGroup(
- ((ExpandableNotificationRow) child).getStatusBarNotification());
+ row.getStatusBarNotification());
if (suppressedSummary) {
continue;
}
+ if (!mStatusBar.shouldShowOnKeyguard(row.getStatusBarNotification())) {
+ continue;
+ }
+ if (row.isRemoved()) {
+ continue;
+ }
availableSpace -= child.getMinHeight() + notificationPadding;
if (availableSpace >= 0 && count < maximum) {
count++;
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 20809ea3a076..ba13e5402231 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -966,7 +966,9 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
super.onDensityOrFontScaleChanged();
mScrimController.onDensityOrFontScaleChanged();
mStatusBarView.onDensityOrFontScaleChanged();
- mBrightnessMirrorController.onDensityOrFontScaleChanged();
+ if (mBrightnessMirrorController != null) {
+ mBrightnessMirrorController.onDensityOrFontScaleChanged();
+ }
inflateSignalClusters();
mIconController.onDensityOrFontScaleChanged();
inflateDismissView();
@@ -975,6 +977,13 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
updateEmptyShadeView();
inflateOverflowContainer();
mStatusBarKeyguardViewManager.onDensityOrFontScaleChanged();
+ mUserInfoController.onDensityOrFontScaleChanged();
+ if (mUserSwitcherController != null) {
+ mUserSwitcherController.onDensityOrFontScaleChanged();
+ }
+ if (mKeyguardUserSwitcher != null) {
+ mKeyguardUserSwitcher.onDensityOrFontScaleChanged();
+ }
}
private void inflateSignalClusters() {
@@ -1541,9 +1550,13 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
ArrayList<ExpandableNotificationRow> toRemove = new ArrayList<>(notificationChildren);
for (int i = 0; i < toRemove.size(); i++) {
toRemove.get(i).setKeepInParent(true);
+ toRemove.get(i).setRemoved(true);
}
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));
}
}
}
@@ -3150,6 +3163,11 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
} else {
pw.println(" mHeadsUpManager: null");
}
+ if (mGroupManager != null) {
+ mGroupManager.dump(fd, pw, args);
+ } else {
+ pw.println(" mGroupManager: null");
+ }
if (KeyguardUpdateMonitor.getInstance(mContext) != null) {
KeyguardUpdateMonitor.getInstance(mContext).dump(fd, pw, args);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java
index e32d51a234af..d6deba06d4da 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java
@@ -57,7 +57,7 @@ public class QuickStatusBarHeader extends BaseStatusBarHeader implements
protected View mSettingsContainer;
private TextView mAlarmStatus;
- private TextView mAlarmStatusCollapsed;
+ private View mAlarmStatusCollapsed;
private QSPanel mQsPanel;
@@ -117,7 +117,7 @@ public class QuickStatusBarHeader extends BaseStatusBarHeader implements
mSettingsContainer = findViewById(R.id.settings_button_container);
mSettingsButton.setOnClickListener(this);
- mAlarmStatusCollapsed = (TextView) findViewById(R.id.alarm_status_collapsed);
+ mAlarmStatusCollapsed = findViewById(R.id.alarm_status_collapsed);
mAlarmStatus = (TextView) findViewById(R.id.alarm_status);
mAlarmStatus.setOnClickListener(this);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DataSaverController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DataSaverController.java
index e6e189f0ffd8..0bca241c8842 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DataSaverController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DataSaverController.java
@@ -91,6 +91,10 @@ public class DataSaverController {
}
@Override
+ public void onRestrictPowerChanged(boolean restrictPower) {
+ }
+
+ @Override
public void onRestrictBackgroundWhitelistChanged(int uid, boolean whitelisted) {
}
};
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcher.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcher.java
index c39d718a44f4..21f3f5e8da06 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcher.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcher.java
@@ -21,8 +21,6 @@ import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.database.DataSetObserver;
-import android.graphics.drawable.BitmapDrawable;
-import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.MotionEvent;
@@ -47,11 +45,12 @@ public class KeyguardUserSwitcher {
private static final boolean ALWAYS_ON = false;
private final Container mUserSwitcherContainer;
- private final ViewGroup mUserSwitcher;
private final KeyguardStatusBarView mStatusBarView;
private final Adapter mAdapter;
private final AppearAnimationUtils mAppearAnimationUtils;
private final KeyguardUserSwitcherScrim mBackground;
+
+ private ViewGroup mUserSwitcher;
private ObjectAnimator mBgAnimator;
private UserSwitcherController mUserSwitcherController;
private boolean mAnimating;
@@ -63,10 +62,8 @@ public class KeyguardUserSwitcher {
context.getResources().getBoolean(R.bool.config_keyguardUserSwitcher) || ALWAYS_ON;
if (userSwitcherController != null && keyguardUserSwitcherEnabled) {
mUserSwitcherContainer = (Container) userSwitcher.inflate();
- mUserSwitcher = (ViewGroup)
- mUserSwitcherContainer.findViewById(R.id.keyguard_user_switcher_inner);
- mBackground = new KeyguardUserSwitcherScrim(mUserSwitcher);
- mUserSwitcher.setBackground(mBackground);
+ mBackground = new KeyguardUserSwitcherScrim(context);
+ reinflateViews();
mStatusBarView = statusBarView;
mStatusBarView.setKeyguardUserSwitcher(this);
panelView.setKeyguardUserSwitcher(this);
@@ -78,7 +75,6 @@ public class KeyguardUserSwitcher {
mUserSwitcherContainer.setKeyguardUserSwitcher(this);
} else {
mUserSwitcherContainer = null;
- mUserSwitcher = null;
mStatusBarView = null;
mAdapter = null;
mAppearAnimationUtils = null;
@@ -86,6 +82,22 @@ public class KeyguardUserSwitcher {
}
}
+ private void reinflateViews() {
+ if (mUserSwitcher != null) {
+ mUserSwitcher.setBackground(null);
+ mUserSwitcher.removeOnLayoutChangeListener(mBackground);
+ }
+ mUserSwitcherContainer.removeAllViews();
+
+ LayoutInflater.from(mUserSwitcherContainer.getContext())
+ .inflate(R.layout.keyguard_user_switcher_inner, mUserSwitcherContainer);
+
+ mUserSwitcher = (ViewGroup) mUserSwitcherContainer.findViewById(
+ R.id.keyguard_user_switcher_inner);
+ mUserSwitcher.addOnLayoutChangeListener(mBackground);
+ mUserSwitcher.setBackground(mBackground);
+ }
+
public void setKeyguard(boolean keyguard, boolean animate) {
if (mUserSwitcher != null) {
if (keyguard && shouldExpandByDefault()) {
@@ -228,6 +240,13 @@ public class KeyguardUserSwitcher {
}
};
+ public void onDensityOrFontScaleChanged() {
+ if (mUserSwitcherContainer != null) {
+ reinflateViews();
+ refresh();
+ }
+ }
+
public static class Adapter extends UserSwitcherController.BaseUserAdapter implements
View.OnClickListener {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherScrim.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherScrim.java
index 353e07d6c8c5..49f5bcdd5a44 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherScrim.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherScrim.java
@@ -16,6 +16,7 @@
package com.android.systemui.statusbar.policy;
+import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorFilter;
@@ -45,9 +46,8 @@ public class KeyguardUserSwitcherScrim extends Drawable
private Paint mRadialGradientPaint = new Paint();
private int mLayoutWidth;
- public KeyguardUserSwitcherScrim(View host) {
- host.addOnLayoutChangeListener(this);
- mDarkColor = host.getContext().getColor(
+ public KeyguardUserSwitcherScrim(Context context) {
+ mDarkColor = context.getColor(
R.color.keyguard_user_switcher_background_gradient_color);
}
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 a855aed88694..095265a0f329 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 class RemoteInputView extends LinearLayout implements View.OnClickListene
public boolean requestScrollTo() {
findScrollContainer();
- mScrollContainer.scrollTo(mScrollContainerChild);
+ mScrollContainer.lockScrollTo(mScrollContainerChild);
return true;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserInfoController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserInfoController.java
index bae5bdab07bc..c5a4f5ece746 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserInfoController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserInfoController.java
@@ -50,7 +50,6 @@ public final class UserInfoController {
new ArrayList<OnUserInfoChangedListener>();
private AsyncTask<Void, Void, Pair<String, Drawable>> mUserInfoTask;
- private boolean mUseDefaultAvatar;
private String mUserName;
private Drawable mUserDrawable;
@@ -58,7 +57,6 @@ public final class UserInfoController {
mContext = context;
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_USER_SWITCHED);
- filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
mContext.registerReceiver(mReceiver, filter);
IntentFilter profileFilter = new IntentFilter();
@@ -83,10 +81,6 @@ public final class UserInfoController {
final String action = intent.getAction();
if (Intent.ACTION_USER_SWITCHED.equals(action)) {
reloadUserInfo();
- } else if (Intent.ACTION_CONFIGURATION_CHANGED.equals(action)) {
- if (mUseDefaultAvatar) {
- reloadUserInfo();
- }
}
}
};
@@ -159,7 +153,6 @@ public final class UserInfoController {
} else {
avatar = UserIcons.getDefaultUserIcon(isGuest? UserHandle.USER_NULL : userId,
/* light= */ true);
- mUseDefaultAvatar = true;
}
// If it's a single-user device, get the profile name, since the nickname is not
@@ -202,6 +195,10 @@ public final class UserInfoController {
}
}
+ public void onDensityOrFontScaleChanged() {
+ reloadUserInfo();
+ }
+
public interface OnUserInfoChangedListener {
public void onUserInfoChanged(String name, Drawable picture);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
index 6800772b754f..415b7a18e553 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
@@ -23,7 +23,6 @@ import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
-import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
@@ -169,12 +168,13 @@ public class UserSwitcherController {
return;
}
+ boolean forceAllUsers = mForcePictureLoadForUserId.get(UserHandle.USER_ALL);
SparseArray<Bitmap> bitmaps = new SparseArray<>(mUsers.size());
final int N = mUsers.size();
for (int i = 0; i < N; i++) {
UserRecord r = mUsers.get(i);
- if (r == null || r.picture == null ||
- r.info == null || mForcePictureLoadForUserId.get(r.info.id)) {
+ if (r == null || r.picture == null || r.info == null || forceAllUsers
+ || mForcePictureLoadForUserId.get(r.info.id)) {
continue;
}
bitmaps.put(r.info.id, r.picture);
@@ -600,6 +600,10 @@ public class UserSwitcherController {
return item.info.name;
}
+ public void onDensityOrFontScaleChanged() {
+ refreshUsers(UserHandle.USER_ALL);
+ }
+
public static abstract class BaseUserAdapter extends BaseAdapter {
final UserSwitcherController mController;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java
index a1e89b75a972..dafaf61df1ea 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java
@@ -103,9 +103,8 @@ public class NotificationChildrenContainer extends ViewGroup {
int childCount = Math.min(mChildren.size(), NUMBER_OF_CHILDREN_WHEN_CHILDREN_EXPANDED);
for (int i = 0; i < childCount; i++) {
View child = mChildren.get(i);
- if (child.getVisibility() == View.GONE) {
- continue;
- }
+ // We need to layout all children even the GONE ones, such that the heights are
+ // calculated correctly as they are used to calculate how many we can fit on the screen
child.layout(0, 0, child.getMeasuredWidth(), child.getMeasuredHeight());
mDividers.get(i).layout(0, 0, getWidth(), mDividerHeight);
}
@@ -138,17 +137,19 @@ public class NotificationChildrenContainer extends ViewGroup {
int overflowIndex = childCount > collapsedChildren ? collapsedChildren - 1 : -1;
for (int i = 0; i < childCount; i++) {
ExpandableNotificationRow child = mChildren.get(i);
+ // We need to measure all children even the GONE ones, such that the heights are
+ // calculated correctly as they are used to calculate how many we can fit on the screen.
boolean isOverflow = i == overflowIndex;
child.setSingleLineWidthIndention(isOverflow && mOverflowNumber != null
? mOverflowNumber.getMeasuredWidth()
: 0);
child.measure(widthMeasureSpec, newHeightSpec);
- height += child.getMeasuredHeight();
-
// layout the divider
View divider = mDividers.get(i);
divider.measure(widthMeasureSpec, dividerHeightSpec);
- height += mDividerHeight;
+ if (child.getVisibility() != GONE) {
+ height += child.getMeasuredHeight() + mDividerHeight;
+ }
}
mRealHeight = height;
if (heightMode != MeasureSpec.UNSPECIFIED) {
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 80eec7ee6fd1..06412758727c 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 @@ public class NotificationStackScrollLayout extends ViewGroup
= new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
+ updateForcedScroll();
updateChildren();
mChildrenUpdateRequested = false;
getViewTreeObserver().removeOnPreDrawListener(this);
@@ -334,6 +335,7 @@ public class NotificationStackScrollLayout extends ViewGroup
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") {
@@ -481,19 +483,22 @@ public class NotificationStackScrollLayout extends ViewGroup
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
- measureChildren(widthMeasureSpec, heightMeasureSpec);
+ // We need to measure all children even the GONE ones, such that the heights are calculated
+ // correctly as they are used to calculate how many we can fit on the screen.
+ final int size = getChildCount();
+ for (int i = 0; i < size; i++) {
+ measureChild(getChildAt(i), widthMeasureSpec, heightMeasureSpec);
+ }
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
-
// we layout all our children centered on the top
float centerX = getWidth() / 2.0f;
for (int i = 0; i < getChildCount(); i++) {
View child = getChildAt(i);
- if (child.getVisibility() == GONE) {
- continue;
- }
+ // We need to layout all children even the GONE ones, such that the heights are
+ // calculated correctly as they are used to calculate how many we can fit on the screen
float width = child.getMeasuredWidth();
float height = child.getMeasuredHeight();
child.layout((int) (centerX - width / 2.0f),
@@ -591,6 +596,23 @@ public class NotificationStackScrollLayout extends ViewGroup
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 +1000,19 @@ public class NotificationStackScrollLayout extends ViewGroup
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 +1023,15 @@ public class NotificationStackScrollLayout extends ViewGroup
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 +1150,7 @@ public class NotificationStackScrollLayout extends ViewGroup
if (ev.getY() < mQsContainer.getBottom()) {
return false;
}
+ mForcedScroll = null;
initVelocityTrackerIfNotExists();
mVelocityTracker.addMovement(ev);
@@ -2342,9 +2382,9 @@ public class NotificationStackScrollLayout extends ViewGroup
}
private void updateHideSensitiveForChild(View child) {
- if (mAmbientState.isHideSensitive() && child instanceof ExpandableView) {
+ if (child instanceof ExpandableView) {
ExpandableView expandableView = (ExpandableView) child;
- expandableView.setHideSensitiveForIntrinsicHeight(true);
+ expandableView.setHideSensitiveForIntrinsicHeight(mAmbientState.isHideSensitive());
}
}
@@ -2787,6 +2827,14 @@ public class NotificationStackScrollLayout extends ViewGroup
}
@Override
+ public void clearChildFocus(View child) {
+ super.clearChildFocus(child);
+ if (mForcedScroll == child) {
+ mForcedScroll = null;
+ }
+ }
+
+ @Override
public void requestDisallowLongPress() {
removeLongPressCallback();
}
@@ -2851,7 +2899,7 @@ public class NotificationStackScrollLayout extends ViewGroup
private void clearTransientViews(ViewGroup viewGroup) {
while (viewGroup != null && viewGroup.getTransientViewCount() != 0) {
- viewGroup.removeTransientView(getTransientView(0));
+ viewGroup.removeTransientView(viewGroup.getTransientView(0));
}
}
@@ -3590,6 +3638,15 @@ public class NotificationStackScrollLayout extends ViewGroup
}
/**
+ * 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 17b7871bbfe0..b9d12ce8f151 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 @@ public interface ScrollContainer {
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 f49067dbcaf6..e8472ac5c8d5 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 @@ public class StackStateAnimator {
// 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 fd4c71e12fb2..c417fe8ae5cc 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants.proto
@@ -2191,21 +2191,6 @@ message MetricsEvent {
// 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 e1695e03e564..7f977dd425fd 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 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
}
if (userState.mIsDisplayMagnificationEnabled ||
- userHasMagnificationServicesLocked(userState)) {
+ userHasListeningMagnificationServicesLocked(userState)) {
// Initialize the magnification controller if necessary
getMagnificationController();
mMagnificationController.register();
@@ -1761,6 +1761,22 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
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 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
}
@Override
- public Region getMagnifiedRegion() {
+ public Region getMagnificationRegion() {
synchronized (mLock) {
+ final Region region = Region.obtain();
if (!isCalledForCurrentUserLocked()) {
- return Region.obtain();
+ 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();
+ }
}
- }
- final long identity = Binder.clearCallingIdentity();
- try {
- final Region region = Region.obtain();
- getMagnificationController().getMagnificationRegion(region);
- return region;
- } finally {
- Binder.restoreCallingIdentity(identity);
}
}
@@ -2940,13 +2965,17 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
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 027b6e2c83e2..7886b9ea7fad 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 @@ class MagnificationController {
}
}
+ /**
+ * 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 @@ class MagnificationController {
*/
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/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java
index 7da247a45341..1edc9b18c697 100644
--- a/services/core/java/com/android/server/AlarmManagerService.java
+++ b/services/core/java/com/android/server/AlarmManagerService.java
@@ -3067,7 +3067,7 @@ class AlarmManagerService extends SystemService {
}
} else {
ActivityManagerNative.noteWakeupAlarm(
- alarm.operation, -1, alarm.packageName, alarm.statsTag);
+ alarm.operation, alarm.uid, alarm.packageName, alarm.statsTag);
}
}
}
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 06255a29f98b..8763b93f31b9 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -30,10 +30,12 @@ import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
import static android.net.NetworkPolicyManager.RULE_ALLOW_ALL;
import static android.net.NetworkPolicyManager.RULE_ALLOW_METERED;
-import static android.net.NetworkPolicyManager.RULE_REJECT_ALL;
+import static android.net.NetworkPolicyManager.MASK_METERED_NETWORKS;
+import static android.net.NetworkPolicyManager.MASK_ALL_NETWORKS;
+import static android.net.NetworkPolicyManager.RULE_NONE;
import static android.net.NetworkPolicyManager.RULE_REJECT_METERED;
import static android.net.NetworkPolicyManager.RULE_TEMPORARY_ALLOW_METERED;
-import static android.net.NetworkPolicyManager.RULE_UNKNOWN;
+import static android.net.NetworkPolicyManager.uidRulesToString;
import android.annotation.Nullable;
import android.app.BroadcastOptions;
@@ -216,6 +218,9 @@ public class ConnectivityService extends IConnectivityManager.Stub
/** Flag indicating if background data is restricted. */
@GuardedBy("mRulesLock")
private boolean mRestrictBackground;
+ /** Flag indicating if background data is restricted due to battery savings. */
+ @GuardedBy("mRulesLock")
+ private boolean mRestrictPower;
final private Context mContext;
private int mNetworkPreference;
@@ -664,9 +669,10 @@ public class ConnectivityService extends IConnectivityManager.Stub
try {
mPolicyManager.setConnectivityListener(mPolicyListener);
mRestrictBackground = mPolicyManager.getRestrictBackground();
+ mRestrictPower = mPolicyManager.getRestrictPower();
} catch (RemoteException e) {
// ouch, no rules updates means some processes may never get network
- loge("unable to register INetworkPolicyListener" + e.toString());
+ loge("unable to register INetworkPolicyListener" + e);
}
final PowerManager powerManager = (PowerManager) context.getSystemService(
@@ -915,24 +921,36 @@ public class ConnectivityService extends IConnectivityManager.Stub
final String iface = (lp == null ? "" : lp.getInterfaceName());
synchronized (mRulesLock) {
networkMetered = mMeteredIfaces.contains(iface);
- uidRules = mUidRules.get(uid, RULE_UNKNOWN);
+ uidRules = mUidRules.get(uid, RULE_NONE);
}
- switch (uidRules) {
- case RULE_ALLOW_ALL:
- case RULE_ALLOW_METERED:
- case RULE_TEMPORARY_ALLOW_METERED:
- return false;
- case RULE_REJECT_METERED:
- return networkMetered;
- case RULE_REJECT_ALL:
- return true;
- case RULE_UNKNOWN:
- default:
- // When background data is restricted device-wide, the default
- // behavior for apps should be like RULE_REJECT_METERED
- return mRestrictBackground ? networkMetered : false;
+ boolean allowed = true;
+ // Check Data Saver Mode first...
+ if (networkMetered) {
+ if ((uidRules & RULE_REJECT_METERED) != 0) {
+ if (LOGD_RULES) Log.d(TAG, "uid " + uid + " is blacklisted");
+ // Explicitly blacklisted.
+ allowed = false;
+ } else {
+ allowed = !mRestrictBackground
+ || (uidRules & RULE_ALLOW_METERED) != 0
+ || (uidRules & RULE_TEMPORARY_ALLOW_METERED) != 0;
+ if (LOGD_RULES) Log.d(TAG, "allowed status for uid " + uid + " when"
+ + " mRestrictBackground=" + mRestrictBackground
+ + ", whitelisted=" + ((uidRules & RULE_ALLOW_METERED) != 0)
+ + ", tempWhitelist= + ((uidRules & RULE_TEMPORARY_ALLOW_METERED) != 0)"
+ + ": " + allowed);
+ }
+ }
+ // ...then Battery Saver Mode.
+ if (allowed && mRestrictPower) {
+ allowed = (uidRules & RULE_ALLOW_ALL) != 0;
+ if (LOGD_RULES) Log.d(TAG, "allowed status for uid " + uid + " when"
+ + " mRestrictPower=" + mRestrictPower
+ + ", whitelisted=" + ((uidRules & RULE_ALLOW_ALL) != 0)
+ + ": " + allowed);
}
+ return !allowed;
}
private void maybeLogBlockedNetworkInfo(NetworkInfo ni, int uid) {
@@ -1379,7 +1397,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
synchronized (mRulesLock) {
// skip update when we've already applied rules
- final int oldRules = mUidRules.get(uid, RULE_ALLOW_ALL);
+ final int oldRules = mUidRules.get(uid, RULE_NONE);
if (oldRules == uidRules) return;
mUidRules.put(uid, uidRules);
@@ -1421,6 +1439,18 @@ public class ConnectivityService extends IConnectivityManager.Stub
}
@Override
+ public void onRestrictPowerChanged(boolean restrictPower) {
+ // caller is NPMS, since we only register with them
+ if (LOGD_RULES) {
+ log("onRestrictPowerChanged(restrictPower=" + restrictPower + ")");
+ }
+
+ synchronized (mRulesLock) {
+ mRestrictPower = restrictPower;
+ }
+ }
+
+ @Override
public void onRestrictBackgroundWhitelistChanged(int uid, boolean whitelisted) {
if (LOGD_RULES) {
// caller is NPMS, since we only register with them
@@ -1861,6 +1891,25 @@ public class ConnectivityService extends IConnectivityManager.Stub
pw.println(mRestrictBackground);
pw.println();
+ pw.print("Restrict power: ");
+ pw.println(mRestrictPower);
+ pw.println();
+
+ pw.println("Status for known UIDs:");
+ pw.increaseIndent();
+ final int size = mUidRules.size();
+ for (int i = 0; i < size; i++) {
+ final int uid = mUidRules.keyAt(i);
+ pw.print("UID=");
+ pw.print(uid);
+ final int uidRules = mUidRules.get(uid, RULE_NONE);
+ pw.print(" rules=");
+ pw.print(uidRulesToString(uidRules));
+ pw.println();
+ }
+ pw.println();
+ pw.decreaseIndent();
+
pw.println("Network Requests:");
pw.increaseIndent();
for (NetworkRequestInfo nri : mNetworkRequests.values()) {
@@ -3982,9 +4031,9 @@ public class ConnectivityService extends IConnectivityManager.Stub
synchronized(mRulesLock) {
uidRules = mUidRules.get(uid, RULE_ALLOW_ALL);
}
- if (uidRules != RULE_ALLOW_ALL) {
+ if ((uidRules & RULE_ALLOW_ALL) == 0) {
// we could silently fail or we can filter the available nets to only give
- // them those they have access to. Chose the more useful
+ // them those they have access to. Chose the more useful option.
networkCapabilities.addCapability(NET_CAPABILITY_NOT_METERED);
}
}
diff --git a/services/core/java/com/android/server/LockSettingsService.java b/services/core/java/com/android/server/LockSettingsService.java
index 434464c90a09..5b6117d55633 100644
--- a/services/core/java/com/android/server/LockSettingsService.java
+++ b/services/core/java/com/android/server/LockSettingsService.java
@@ -340,8 +340,9 @@ public class LockSettingsService extends ILockSettings.Stub {
}
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.
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index 2418160255f8..e5b301e803af 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -330,6 +330,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub
if (DBG) Slog.d(TAG, "Awaiting socket connection");
connectedSignal.await();
if (DBG) Slog.d(TAG, "Connected");
+ service.connectNativeNetdService();
return service;
}
@@ -560,11 +561,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub
}
}
- /**
- * Prepare native daemon once connected, enabling modules and pushing any
- * existing in-memory rules.
- */
- private void prepareNativeDaemon() {
+ private void connectNativeNetdService() {
boolean nativeServiceAvailable = false;
try {
mNetdService = INetd.Stub.asInterface(ServiceManager.getService(NETD_SERVICE_NAME));
@@ -573,6 +570,13 @@ public class NetworkManagementService extends INetworkManagementService.Stub
if (!nativeServiceAvailable) {
Slog.wtf(TAG, "Can't connect to NativeNetdService " + NETD_SERVICE_NAME);
}
+ }
+
+ /**
+ * Prepare native daemon once connected, enabling modules and pushing any
+ * existing in-memory rules.
+ */
+ private void prepareNativeDaemon() {
mBandwidthControlEnabled = false;
@@ -767,12 +771,16 @@ public class NetworkManagementService extends INetworkManagementService.Stub
// event is dispatched from internal NDC thread, so we prepare the
// daemon back on main thread.
if (mConnectedSignal != null) {
+ // The system is booting and we're connecting to netd for the first time.
mConnectedSignal.countDown();
mConnectedSignal = null;
} else {
+ // We're reconnecting to netd after the socket connection
+ // was interrupted (e.g., if it crashed).
mFgHandler.post(new Runnable() {
@Override
public void run() {
+ connectNativeNetdService();
prepareNativeDaemon();
}
});
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index 98b3b088399a..a9a53a2ccee1 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 @@ public class AccountManagerService
}
}
- 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 @@ public class AccountManagerService
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/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 94118e62b495..313ca9a95415 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -390,6 +390,11 @@ public final class ActivityManagerService extends ActivityManagerNative
private static final String TAG_VISIBILITY = TAG + POSTFIX_VISIBILITY;
private static final String TAG_VISIBLE_BEHIND = TAG + POSTFIX_VISIBLE_BEHIND;
+ // Mock "pretend we're idle now" broadcast action to the job scheduler; declared
+ // here so that while the job scheduler can depend on AMS, the other way around
+ // need not be the case.
+ public static final String ACTION_TRIGGER_IDLE = "com.android.server.ACTION_TRIGGER_IDLE";
+
/** Control over CPU and battery monitoring */
// write battery stats every 30 minutes.
static final long BATTERY_STATS_TIME = 30 * 60 * 1000;
@@ -1508,6 +1513,10 @@ public final class ActivityManagerService extends ActivityManagerNative
PackageManagerInternal mPackageManagerInt;
+ // VoiceInteraction session ID that changes for each new request except when
+ // being called for multiwindow assist in a single session.
+ private int mViSessionId = 1000;
+
final class KillHandler extends Handler {
static final int KILL_PROCESS_GROUP_MSG = 4000;
@@ -11476,7 +11485,7 @@ public final class ActivityManagerService extends ActivityManagerNative
mWindowManager.setEventDispatching(mBooted && !mShuttingDown);
}
- public void setLockScreenShown(boolean shown) {
+ public void setLockScreenShown(boolean showing, boolean occluded) {
if (checkCallingPermission(android.Manifest.permission.DEVICE_POWER)
!= PackageManager.PERMISSION_GRANTED) {
throw new SecurityException("Requires permission "
@@ -11486,8 +11495,17 @@ public final class ActivityManagerService extends ActivityManagerNative
synchronized(this) {
long ident = Binder.clearCallingIdentity();
try {
- if (DEBUG_LOCKSCREEN) logLockScreen(" shown=" + shown);
- mLockScreenShown = shown ? LOCK_SCREEN_SHOWN : LOCK_SCREEN_HIDDEN;
+ if (DEBUG_LOCKSCREEN) logLockScreen(" showing=" + showing + " occluded=" + occluded);
+ mLockScreenShown = (showing && !occluded) ? LOCK_SCREEN_SHOWN : LOCK_SCREEN_HIDDEN;
+ if (showing && occluded) {
+ // The lock screen is currently showing, but is occluded by a window that can
+ // show on top of the lock screen. In this can we want to dismiss the docked
+ // stack since it will be complicated/risky to try to put the activity on top
+ // of the lock screen in the right fullscreen configuration.
+ mStackSupervisor.moveTasksToFullscreenStackLocked(DOCKED_STACK_ID,
+ mStackSupervisor.mFocusedStack.getStackId() == DOCKED_STACK_ID);
+ }
+
updateSleepIfNeededLocked();
} finally {
Binder.restoreCallingIdentity(ident);
@@ -11867,7 +11885,8 @@ public final class ActivityManagerService extends ActivityManagerNative
@Override
public Bundle getAssistContextExtras(int requestType) {
PendingAssistExtras pae = enqueueAssistContext(requestType, null, null, null,
- null, null, true, UserHandle.getCallingUserId(), null, PENDING_ASSIST_EXTRAS_TIMEOUT);
+ null, null, true /* focused */, true /* newSessionId */,
+ UserHandle.getCallingUserId(), null, PENDING_ASSIST_EXTRAS_TIMEOUT);
if (pae == null) {
return null;
}
@@ -11932,16 +11951,16 @@ public final class ActivityManagerService extends ActivityManagerNative
@Override
public boolean requestAssistContextExtras(int requestType, IResultReceiver receiver,
Bundle receiverExtras,
- IBinder activityToken, boolean focused) {
+ IBinder activityToken, boolean focused, boolean newSessionId) {
return enqueueAssistContext(requestType, null, null, receiver, receiverExtras,
- activityToken, focused,
+ activityToken, focused, newSessionId,
UserHandle.getCallingUserId(), null, PENDING_ASSIST_EXTRAS_LONG_TIMEOUT)
!= null;
}
private PendingAssistExtras enqueueAssistContext(int requestType, Intent intent, String hint,
- IResultReceiver receiver, Bundle receiverExtras, IBinder activityToken, boolean focused,
- int userHandle, Bundle args, long timeout) {
+ IResultReceiver receiver, Bundle receiverExtras, IBinder activityToken,
+ boolean focused, boolean newSessionId, int userHandle, Bundle args, long timeout) {
enforceCallingPermission(android.Manifest.permission.GET_TOP_ACTIVITY_INFO,
"enqueueAssistContext()");
synchronized (this) {
@@ -11981,9 +12000,13 @@ public final class ActivityManagerService extends ActivityManagerNative
extras.putInt(Intent.EXTRA_ASSIST_UID, activity.app.uid);
pae = new PendingAssistExtras(activity, extras, intent, hint, receiver, receiverExtras,
userHandle);
+ // Increment the sessionId if necessary
+ if (newSessionId) {
+ mViSessionId++;
+ }
try {
activity.app.thread.requestAssistContextExtras(activity.appToken, pae,
- requestType);
+ requestType, mViSessionId);
mPendingAssistExtras.add(pae);
mUiHandler.postDelayed(pae, timeout);
} catch (RemoteException e) {
@@ -12088,7 +12111,8 @@ public final class ActivityManagerService extends ActivityManagerNative
public boolean launchAssistIntent(Intent intent, int requestType, String hint, int userHandle,
Bundle args) {
- return enqueueAssistContext(requestType, intent, hint, null, null, null, true,
+ return enqueueAssistContext(requestType, intent, hint, null, null, null,
+ true /* focused */, true /* newSessionId */,
userHandle, args, PENDING_ASSIST_EXTRAS_TIMEOUT) != null;
}
@@ -12649,6 +12673,26 @@ public final class ActivityManagerService extends ActivityManagerNative
}
}
+ @Override
+ public void sendIdleJobTrigger() {
+ if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
+ != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException("Requires permission "
+ + android.Manifest.permission.SET_ACTIVITY_WATCHER);
+ }
+
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ Intent intent = new Intent(ACTION_TRIGGER_IDLE)
+ .setPackage("android")
+ .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+ broadcastIntent(null, intent, null, null, 0, null, null, null,
+ android.app.AppOpsManager.OP_NONE, null, true, false, UserHandle.USER_ALL);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+
private void retrieveSettings() {
final ContentResolver resolver = mContext.getContentResolver();
final boolean freeformWindowManagement =
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index dac710d759bd..243c8872f7fb 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -1008,13 +1008,14 @@ final class ActivityStack {
void goToSleep() {
ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
- // Make sure any stopped but visible activities are now sleeping.
+ // Make sure any paused or stopped but visible activities are now sleeping.
// This ensures that the activity's onStop() is called.
for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
final ActivityRecord r = activities.get(activityNdx);
- if (r.state == ActivityState.STOPPING || r.state == ActivityState.STOPPED) {
+ if (r.state == ActivityState.STOPPING || r.state == ActivityState.STOPPED
+ || r.state == ActivityState.PAUSED || r.state == ActivityState.PAUSING) {
r.setSleeping(true);
}
}
@@ -3340,14 +3341,12 @@ final class ActivityStack {
} catch (RemoteException re) {
// Ok
}
- // TODO: VI This is redundant in some cases
mService.finishRunningVoiceLocked();
break;
}
}
}
}
- Slog.d(TAG, "ActivityStack.finishVoiceTask()");
if (didOne) {
mService.updateOomAdjLocked();
diff --git a/services/core/java/com/android/server/am/RecentTasks.java b/services/core/java/com/android/server/am/RecentTasks.java
index 88faee73322f..cea76f236fc9 100644
--- a/services/core/java/com/android/server/am/RecentTasks.java
+++ b/services/core/java/com/android/server/am/RecentTasks.java
@@ -65,6 +65,9 @@ class RecentTasks extends ArrayList<TaskRecord> {
private static final int MAX_RECENT_BITMAPS = 3;
private static final int DEFAULT_INITIAL_CAPACITY = 5;
+ // Whether or not to move all affiliated tasks to the front when one of the tasks is launched
+ private static final boolean MOVE_AFFILIATED_TASKS_TO_FRONT = false;
+
/**
* Save recent tasks information across reboots.
*/
@@ -513,7 +516,7 @@ class RecentTasks extends ArrayList<TaskRecord> {
if (task.inRecents) {
int taskIndex = indexOf(task);
if (taskIndex >= 0) {
- if (!isAffiliated) {
+ if (!isAffiliated || MOVE_AFFILIATED_TASKS_TO_FRONT) {
// Simple case: this is not an affiliated task, so we just move it to the front.
remove(taskIndex);
add(0, task);
diff --git a/services/core/java/com/android/server/am/ServiceRecord.java b/services/core/java/com/android/server/am/ServiceRecord.java
index bc297dec834a..0a081e9809ea 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 @@ final class ServiceRecord extends Binder {
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 @@ final class ServiceRecord extends Binder {
}
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/fingerprint/FingerprintService.java b/services/core/java/com/android/server/fingerprint/FingerprintService.java
index ae01635c0905..142426dd4fd9 100644
--- a/services/core/java/com/android/server/fingerprint/FingerprintService.java
+++ b/services/core/java/com/android/server/fingerprint/FingerprintService.java
@@ -968,8 +968,8 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe
}
daemon.setActiveGroup(userId, fpDir.getAbsolutePath().getBytes());
mCurrentUserId = userId;
- mCurrentAuthenticatorId = daemon.getAuthenticatorId();
}
+ mCurrentAuthenticatorId = daemon.getAuthenticatorId();
} catch (RemoteException e) {
Slog.e(TAG, "Failed to setActiveGroup():", e);
}
diff --git a/services/core/java/com/android/server/job/controllers/ConnectivityController.java b/services/core/java/com/android/server/job/controllers/ConnectivityController.java
index 9fd22686a9a0..e0179dcc9586 100644
--- a/services/core/java/com/android/server/job/controllers/ConnectivityController.java
+++ b/services/core/java/com/android/server/job/controllers/ConnectivityController.java
@@ -170,6 +170,11 @@ public class ConnectivityController extends StateController implements
}
@Override
+ public void onRestrictPowerChanged(boolean restrictPower) {
+ updateTrackedJobs(-1);
+ }
+
+ @Override
public void onRestrictBackgroundChanged(boolean restrictBackground) {
updateTrackedJobs(-1);
}
diff --git a/services/core/java/com/android/server/job/controllers/IdleController.java b/services/core/java/com/android/server/job/controllers/IdleController.java
index c7a679cc4697..5899d1647ad8 100644
--- a/services/core/java/com/android/server/job/controllers/IdleController.java
+++ b/services/core/java/com/android/server/job/controllers/IdleController.java
@@ -28,15 +28,13 @@ import android.content.IntentFilter;
import android.os.SystemClock;
import android.util.Slog;
+import com.android.server.am.ActivityManagerService;
import com.android.server.job.JobSchedulerService;
import com.android.server.job.StateChangedListener;
public class IdleController extends StateController {
private static final String TAG = "IdleController";
- private static final String ACTION_TRIGGER_IDLE =
- "com.android.server.task.controllers.IdleController.ACTION_TRIGGER_IDLE";
-
// Policy: we decide that we're "idle" if the device has been unused /
// screen off or dreaming for at least this long
private long mInactivityIdleThreshold;
@@ -113,7 +111,7 @@ public class IdleController extends StateController {
public IdlenessTracker() {
mAlarm = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
- Intent intent = new Intent(ACTION_TRIGGER_IDLE)
+ Intent intent = new Intent(ActivityManagerService.ACTION_TRIGGER_IDLE)
.setPackage("android")
.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
mIdleTriggerIntent = PendingIntent.getBroadcast(mContext, 0, intent, 0);
@@ -140,7 +138,7 @@ public class IdleController extends StateController {
filter.addAction(Intent.ACTION_DREAMING_STOPPED);
// Debugging/instrumentation
- filter.addAction(ACTION_TRIGGER_IDLE);
+ filter.addAction(ActivityManagerService.ACTION_TRIGGER_IDLE);
mContext.registerReceiver(this, filter);
}
@@ -176,7 +174,7 @@ public class IdleController extends StateController {
mScreenOn = false;
mAlarm.setWindow(AlarmManager.ELAPSED_REALTIME_WAKEUP,
when, mIdleWindowSlop, mIdleTriggerIntent);
- } else if (action.equals(ACTION_TRIGGER_IDLE)) {
+ } else if (action.equals(ActivityManagerService.ACTION_TRIGGER_IDLE)) {
// idle time starts now. Do not set mIdle if screen is on.
if (!mIdle && !mScreenOn) {
if (DEBUG) {
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index a6055c1716f7..344ba179e4c7 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -48,11 +48,16 @@ import static android.net.NetworkPolicyManager.FIREWALL_RULE_DEFAULT;
import static android.net.NetworkPolicyManager.FIREWALL_RULE_DENY;
import static android.net.NetworkPolicyManager.POLICY_NONE;
import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND;
+import static android.net.NetworkPolicyManager.RULE_ALLOW_ALL;
import static android.net.NetworkPolicyManager.RULE_ALLOW_METERED;
+import static android.net.NetworkPolicyManager.MASK_METERED_NETWORKS;
+import static android.net.NetworkPolicyManager.MASK_ALL_NETWORKS;
+import static android.net.NetworkPolicyManager.RULE_NONE;
+import static android.net.NetworkPolicyManager.RULE_REJECT_ALL;
import static android.net.NetworkPolicyManager.RULE_REJECT_METERED;
import static android.net.NetworkPolicyManager.RULE_TEMPORARY_ALLOW_METERED;
-import static android.net.NetworkPolicyManager.RULE_UNKNOWN;
import static android.net.NetworkPolicyManager.computeLastCycleBoundary;
+import static android.net.NetworkPolicyManager.uidRulesToString;
import static android.net.NetworkTemplate.MATCH_MOBILE_3G_LOWER;
import static android.net.NetworkTemplate.MATCH_MOBILE_4G;
import static android.net.NetworkTemplate.MATCH_MOBILE_ALL;
@@ -261,6 +266,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
private static final int MSG_RESTRICT_BACKGROUND_WHITELIST_CHANGED = 9;
private static final int MSG_UPDATE_INTERFACE_QUOTA = 10;
private static final int MSG_REMOVE_INTERFACE_QUOTA = 11;
+ private static final int MSG_RESTRICT_POWER_CHANGED = 12;
private final Context mContext;
private final IActivityManager mActivityManager;
@@ -551,9 +557,19 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
updateRulesForGlobalChangeLocked(true);
}
}
+ mHandler.obtainMessage(MSG_RESTRICT_POWER_CHANGED,
+ enabled ? 1 : 0, 0).sendToTarget();
}
});
+ final boolean oldRestrictPower = mRestrictPower;
mRestrictPower = mPowerManagerInternal.getLowPowerModeEnabled();
+ if (mRestrictPower != oldRestrictPower) {
+ // Some early services may have read the default value,
+ // so notify them that it's changed
+ mHandler.obtainMessage(MSG_RESTRICT_POWER_CHANGED,
+ mRestrictPower ? 1 : 0, 0).sendToTarget();
+ }
+
mSystemReady = true;
// read policy from disk
@@ -2048,13 +2064,15 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
private boolean removeRestrictBackgroundWhitelistedUidLocked(int uid, boolean uidDeleted,
boolean updateNow) {
final boolean oldStatus = mRestrictBackgroundWhitelistUids.get(uid);
- if (!oldStatus) {
+ if (!oldStatus && !uidDeleted) {
if (LOGD) Slog.d(TAG, "uid " + uid + " was not whitelisted before");
return false;
}
final boolean needFirewallRules = uidDeleted || isUidValidForWhitelistRules(uid);
- Slog.i(TAG, "removing uid " + uid + " from restrict background whitelist");
- mRestrictBackgroundWhitelistUids.delete(uid);
+ if (oldStatus) {
+ Slog.i(TAG, "removing uid " + uid + " from restrict background whitelist");
+ mRestrictBackgroundWhitelistUids.delete(uid);
+ }
if (mDefaultRestrictBackgroundWhitelistUids.get(uid)
&& !mRestrictBackgroundWhitelistRevokedUids.get(uid)) {
if (LOGD) Slog.d(TAG, "Adding uid " + uid
@@ -2128,6 +2146,15 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
}
@Override
+ public boolean getRestrictPower() {
+ mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
+
+ synchronized (mRulesLock) {
+ return mRestrictPower;
+ }
+ }
+
+ @Override
public void setDeviceIdleMode(boolean enabled) {
mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
@@ -2352,7 +2379,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
collectKeys(mUidState, knownUids);
collectKeys(mUidRules, knownUids);
- fout.println("Status for known UIDs:");
+ fout.println("Status for all known UIDs:");
fout.increaseIndent();
size = knownUids.size();
for (int i = 0; i < size; i++) {
@@ -2370,20 +2397,29 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
? " (fg svc)" : " (bg)");
}
- final int rule = mUidRules.get(uid, RULE_UNKNOWN);
- fout.print(" rule=");
- fout.print(ruleToString(rule));
+ final int uidRules = mUidRules.get(uid, RULE_NONE);
+ fout.print(" rules=");
+ fout.print(uidRulesToString(uidRules));
+ fout.println();
+ }
+ fout.decreaseIndent();
+ fout.println("Status for just UIDs with rules:");
+ fout.increaseIndent();
+ size = mUidRules.size();
+ for (int i = 0; i < size; i++) {
+ final int uid = mUidRules.keyAt(i);
+ fout.print("UID=");
+ fout.print(uid);
+ final int uidRules = mUidRules.get(uid, RULE_NONE);
+ fout.print(" rules=");
+ fout.print(uidRulesToString(uidRules));
fout.println();
}
fout.decreaseIndent();
}
}
- private String ruleToString(int rule) {
- return DebugUtils.valueToString(NetworkPolicyManager.class, "RULE_", rule);
- }
-
@Override
public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
String[] args, ResultReceiver resultReceiver) throws RemoteException {
@@ -2564,12 +2600,16 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
enableFirewallChainLocked(chain, enabled);
}
+ private boolean isWhitelistedBatterySaverLocked(int uid) {
+ final int appId = UserHandle.getAppId(uid);
+ return mPowerSaveTempWhitelistAppIds.get(appId) || mPowerSaveWhitelistAppIds.get(appId);
+ }
+
// NOTE: since both fw_dozable and fw_powersave uses the same map
// (mPowerSaveTempWhitelistAppIds) for whitelisting, we can reuse their logic in this method.
private void updateRulesForWhitelistedPowerSaveLocked(int uid, boolean enabled, int chain) {
if (enabled) {
- int appId = UserHandle.getAppId(uid);
- if (mPowerSaveTempWhitelistAppIds.get(appId) || mPowerSaveWhitelistAppIds.get(appId)
+ if (isWhitelistedBatterySaverLocked(uid)
|| isProcStateAllowedWhileIdleOrPowerSaveMode(mUidState.get(uid))) {
setUidFirewallRule(chain, uid, FIREWALL_RULE_ALLOW);
} else {
@@ -2732,7 +2772,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
* <p>There are currently 2 types of restriction rules:
* <ul>
* <li>Battery Saver Mode (also referred as power save).
- * <li>Data Saver Mode (formerly known as restrict background data).
+ * <li>Data Saver Mode (The Feature Formerly Known As 'Restrict Background Data').
* </ul>
*/
private void updateRestrictionRulesForUidLocked(int uid) {
@@ -2777,6 +2817,10 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
* have permission to use the internet.
*
* <p>The {@link #mUidRules} map is used to define the transtion of states of an UID.
+ *
+ * <p>This method also updates the {@link #mUidRules} with the power-related status for the uid
+ * and send the proper {@value #MSG_RULES_CHANGED} notification, although it does not change
+ * the power-related firewall rules per se.
*/
private void updateRuleForRestrictBackgroundLocked(int uid) {
updateRuleForRestrictBackgroundLocked(uid, false);
@@ -2793,42 +2837,70 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
}
final int uidPolicy = mUidPolicy.get(uid, POLICY_NONE);
+ final int oldUidRules = mUidRules.get(uid, RULE_NONE);
final boolean isForeground = isUidForegroundOnRestrictBackgroundLocked(uid);
- final boolean isBlacklisted = (uidPolicy & POLICY_REJECT_METERED_BACKGROUND) != 0;
- final boolean isWhitelisted = mRestrictBackgroundWhitelistUids.get(uid);
- int newRule = RULE_UNKNOWN;
- final int oldRule = mUidRules.get(uid, RULE_UNKNOWN);
+ // Data Saver status.
+ final boolean isDsBlacklisted = (uidPolicy & POLICY_REJECT_METERED_BACKGROUND) != 0;
+ final boolean isDsWhitelisted = mRestrictBackgroundWhitelistUids.get(uid);
+ final int oldDsRule = oldUidRules & MASK_METERED_NETWORKS;
+ int newDsRule = RULE_NONE;
+
+ // Battery Saver status.
+ final boolean isBsWhitelisted = isWhitelistedBatterySaverLocked(uid);
+ final int oldBsRule = oldUidRules & MASK_ALL_NETWORKS;
+ int newBsRule = RULE_NONE;
// First step: define the new rule based on user restrictions and foreground state.
if (isForeground) {
- if (isBlacklisted || (mRestrictBackground && !isWhitelisted)) {
- newRule = RULE_TEMPORARY_ALLOW_METERED;
+ // Data Saver rules
+ if (isDsBlacklisted || (mRestrictBackground && !isDsWhitelisted)) {
+ newDsRule = RULE_TEMPORARY_ALLOW_METERED;
+ } else if (isDsWhitelisted) {
+ newDsRule = RULE_ALLOW_METERED;
+ }
+ // Battery Saver rules
+ if (mRestrictPower) {
+ newBsRule = RULE_ALLOW_ALL;
}
} else {
- if (isBlacklisted) {
- newRule = RULE_REJECT_METERED;
- } else if (isWhitelisted) {
- newRule = RULE_ALLOW_METERED;
+ // Data Saver rules
+ if (isDsBlacklisted) {
+ newDsRule = RULE_REJECT_METERED;
+ } else if (mRestrictBackground && isDsWhitelisted) {
+ newDsRule = RULE_ALLOW_METERED;
+ }
+ // Battery Saver rules
+ if (mRestrictPower) {
+ newBsRule = isBsWhitelisted ? RULE_ALLOW_ALL : RULE_REJECT_ALL;
}
}
+ final int newUidRules = newDsRule | newBsRule;
if (LOGV) {
Log.v(TAG, "updateRuleForRestrictBackgroundLocked(" + uid + "):"
- + " isForeground=" +isForeground + ", isBlacklisted: " + isBlacklisted
- + ", isWhitelisted: " + isWhitelisted + ", newRule: " + ruleToString(newRule)
- + ", oldRule: " + ruleToString(oldRule));
+ + " isForeground=" +isForeground + ", isBlacklisted: " + isDsBlacklisted
+ + ", isDsWhitelisted: " + isDsWhitelisted
+ + ", isBsWhitelisted: " + isBsWhitelisted
+ + ", newUidRules: " + uidRulesToString(newUidRules)
+ + ", oldUidRules: " + uidRulesToString(oldUidRules));
}
- if (newRule == RULE_UNKNOWN) {
+ if (newUidRules == RULE_NONE) {
mUidRules.delete(uid);
} else {
- mUidRules.put(uid, newRule);
+ mUidRules.put(uid, newUidRules);
}
+ boolean changed = false;
+
// Second step: apply bw changes based on change of state.
- if (newRule != oldRule) {
- if (newRule == RULE_TEMPORARY_ALLOW_METERED) {
+
+ // Apply Data Saver rules.
+ if (newDsRule != oldDsRule) {
+ changed = true;
+
+ if ((newDsRule & RULE_TEMPORARY_ALLOW_METERED) != 0) {
// Temporarily whitelist foreground app, removing from blacklist if necessary
// (since bw_penalty_box prevails over bw_happy_box).
@@ -2836,44 +2908,69 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
// TODO: if statement below is used to avoid an unnecessary call to netd / iptables,
// but ideally it should be just:
// setMeteredNetworkBlacklist(uid, isBlacklisted);
- if (isBlacklisted) {
+ if (isDsBlacklisted) {
setMeteredNetworkBlacklist(uid, false);
}
- } else if (oldRule == RULE_TEMPORARY_ALLOW_METERED) {
+ } else if ((oldDsRule & RULE_TEMPORARY_ALLOW_METERED) != 0) {
// Remove temporary whitelist from app that is not on foreground anymore.
// TODO: if statements below are used to avoid unnecessary calls to netd / iptables,
// but ideally they should be just:
// setMeteredNetworkWhitelist(uid, isWhitelisted);
// setMeteredNetworkBlacklist(uid, isBlacklisted);
- if (!isWhitelisted) {
+ if (!isDsWhitelisted) {
setMeteredNetworkWhitelist(uid, false);
}
- if (isBlacklisted) {
+ if (isDsBlacklisted) {
setMeteredNetworkBlacklist(uid, true);
}
- } else if (newRule == RULE_REJECT_METERED || oldRule == RULE_REJECT_METERED) {
+ } else if ((newDsRule & RULE_REJECT_METERED) != 0
+ || (oldDsRule & RULE_REJECT_METERED) != 0) {
// Flip state because app was explicitly added or removed to blacklist.
- setMeteredNetworkBlacklist(uid, isBlacklisted);
- if (oldRule == RULE_REJECT_METERED && isWhitelisted) {
+ setMeteredNetworkBlacklist(uid, isDsBlacklisted);
+ if ((oldDsRule & RULE_REJECT_METERED) != 0 && isDsWhitelisted) {
// Since blacklist prevails over whitelist, we need to handle the special case
// where app is whitelisted and blacklisted at the same time (although such
// scenario should be blocked by the UI), then blacklist is removed.
- setMeteredNetworkWhitelist(uid, isWhitelisted);
+ setMeteredNetworkWhitelist(uid, isDsWhitelisted);
}
- } else if (newRule == RULE_ALLOW_METERED || oldRule == RULE_ALLOW_METERED) {
+ } else if ((newDsRule & RULE_ALLOW_METERED) != 0
+ || (oldDsRule & RULE_ALLOW_METERED) != 0) {
// Flip state because app was explicitly added or removed to whitelist.
- setMeteredNetworkWhitelist(uid, isWhitelisted);
+ setMeteredNetworkWhitelist(uid, isDsWhitelisted);
} else {
// All scenarios should have been covered above
- Log.wtf(TAG, "Unexpected change of state for " + uid
- + ": foreground=" + isForeground + ", whitelisted=" + isWhitelisted
- + ", blacklisted=" + isBlacklisted + ", newRule="
- + ruleToString(newRule) + ", oldRule=" + ruleToString(oldRule));
+ Log.wtf(TAG, "Unexpected change of metered UID state for " + uid
+ + ": foreground=" + isForeground
+ + ", whitelisted=" + isDsWhitelisted
+ + ", blacklisted=" + isDsBlacklisted
+ + ", newRule=" + uidRulesToString(newUidRules)
+ + ", oldRule=" + uidRulesToString(oldUidRules));
}
+ }
- // dispatch changed rule to existing listeners
- mHandler.obtainMessage(MSG_RULES_CHANGED, uid, newRule).sendToTarget();
+ // Apply Battery Saver rules.
+ // NOTE: the firewall rules are changed outside this method, but it's still necessary to
+ // send the MSG_RULES_CHANGED so ConnectivityService can update its internal status.
+ if (newBsRule != oldBsRule) {
+ changed = true;
+ if (newBsRule == RULE_NONE || (newBsRule & RULE_ALLOW_ALL) != 0) {
+ if (LOGV) Log.v(TAG, "Allowing non-metered access for UID " + uid);
+ } else if ((newBsRule & RULE_REJECT_ALL) != 0) {
+ if (LOGV) Log.v(TAG, "Rejecting non-metered access for UID " + uid);
+ } else {
+ // All scenarios should have been covered above
+ Log.wtf(TAG, "Unexpected change of non-metered UID state for " + uid
+ + ": foreground=" + isForeground
+ + ", whitelisted=" + isBsWhitelisted
+ + ", newRule=" + uidRulesToString(newUidRules)
+ + ", oldRule=" + uidRulesToString(oldUidRules));
+ }
+ }
+
+ // Final step: dispatch changed rule to existing listeners
+ if (changed) {
+ mHandler.obtainMessage(MSG_RULES_CHANGED, uid, newUidRules).sendToTarget();
}
}
@@ -2939,6 +3036,16 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
}
}
+ private void dispatchRestrictPowerChanged(INetworkPolicyListener listener,
+ boolean restrictPower) {
+ if (listener != null) {
+ try {
+ listener.onRestrictPowerChanged(restrictPower);
+ } catch (RemoteException ignored) {
+ }
+ }
+ }
+
private Handler.Callback mHandlerCallback = new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {
@@ -2986,6 +3093,11 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
}
return true;
}
+ case MSG_RESTRICT_POWER_CHANGED: {
+ final boolean restrictPower = msg.arg1 != 0;
+ dispatchRestrictPowerChanged(mConnectivityListener, restrictPower);
+ return true;
+ }
case MSG_RESTRICT_BACKGROUND_CHANGED: {
final boolean restrictBackground = msg.arg1 != 0;
dispatchRestrictBackgroundChanged(mConnectivityListener, restrictBackground);
diff --git a/services/core/java/com/android/server/net/NetworkStatsObservers.java b/services/core/java/com/android/server/net/NetworkStatsObservers.java
index 6f781b3ebb6f..230c2e95109e 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 @@ class NetworkStatsObservers {
*/
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 @@ class NetworkStatsObservers {
+ ". 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 @@ class NetworkStatsObservers {
}
}
- 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 @@ class NetworkStatsObservers {
@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 @@ class NetworkStatsObservers {
@Override
protected boolean checkStats() {
- int[] uidsToMonitor = getUidsToMonitor();
-
- 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]);
-
- 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;
- }
+ int[] uidsToMonitor = mCollection.getRelevantUids(mAccessLevel, mCallingUid);
+
+ 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.template + " for uid=" + uidsToMonitor[i]);
+ }
+ if (bytesSoFar > mRequest.thresholdInBytes) {
+ return true;
}
}
return false;
@@ -453,21 +432,6 @@ class NetworkStatsObservers {
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 2c2e9b91b586..8610fa1b7b49 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 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
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 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
}
@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 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
}
@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 0a254029a8f4..ee02a9954a5a 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 @@ public class BackgroundDexOptService extends JobService {
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 f134e40b9c59..89747b5f79b7 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.Log;
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 @@ class PackageDexOptimizer {
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 4adfc3fb7d45..4e48e4d7f6d6 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.app.ResolverActivity;
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 @@ public class PackageManagerService extends IPackageManager.Stub {
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 @@ public class PackageManagerService extends IPackageManager.Stub {
}
}
+ // 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 @@ public class PackageManagerService extends IPackageManager.Stub {
}
}
- 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 @@ public class PackageManagerService extends IPackageManager.Stub {
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 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
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 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
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 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
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 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
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 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
}
}
+ 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 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
final String label;
final int targetSdkVersion;
final PackageFreezer freezer;
+ final int[] installedUserIds;
// reader
synchronized (mPackages) {
@@ -19664,6 +19712,7 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
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 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
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/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index 9ac9930b1711..ae8d1b7a0699 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -260,35 +260,6 @@ class PackageManagerShellCommand extends ShellCommand {
String compilationReason = null;
String checkProfilesRaw = null;
- if (peekNextArg() == null) {
- // No arguments, show help.
- pw.println("Usage: cmd package compile [-c] [-f] [--reset] [-m mode] " +
- "[-r reason] [-a|pkg]");
- pw.println();
- pw.println(" -c Clear profile data");
- pw.println(" -f Force compilation");
- pw.println(" --check-prof val Look at profiles when doing dexopt.");
- pw.println(" Overrides dalvik.vm.usejitprofiles to true of false");
- pw.println(" --reset Reset package");
- pw.println(" -m mode Compilation mode, one of the dex2oat compiler filters");
- pw.println(" verify-none");
- pw.println(" verify-at-runtime");
- pw.println(" verify-profile");
- pw.println(" interpret-only");
- pw.println(" space-profile");
- pw.println(" space");
- pw.println(" speed-profile");
- pw.println(" speed");
- pw.println(" everything");
- pw.println(" -r reason Compiler reason, one of the package manager reasons");
- for (int i = 0; i < PackageManagerServiceCompilerMapping.REASON_STRINGS.length; i++) {
- pw.println(" " +
- PackageManagerServiceCompilerMapping.REASON_STRINGS[i]);
- }
- pw.println(" -a Apply to all packages");
- return 1;
- }
-
String opt;
while ((opt = getNextOption()) != null) {
switch (opt) {
@@ -307,7 +278,7 @@ class PackageManagerShellCommand extends ShellCommand {
case "-r":
compilationReason = getNextArgRequired();
break;
- case "-check-prof":
+ case "--check-prof":
checkProfilesRaw = getNextArgRequired();
break;
case "--reset":
@@ -345,25 +316,12 @@ class PackageManagerShellCommand extends ShellCommand {
String targetCompilerFilter;
if (compilerFilter != null) {
- // Specially recognize default and reset. Otherwise, only accept valid modes.
- if ("default".equals(compilerFilter)) {
- // Use the default mode for background dexopt.
- targetCompilerFilter =
- PackageManagerServiceCompilerMapping.getCompilerFilterForReason(
- PackageManagerService.REASON_BACKGROUND_DEXOPT);
- } else if ("reset".equals(compilerFilter)) {
- // Use the default mode for install.
- targetCompilerFilter =
- PackageManagerServiceCompilerMapping.getCompilerFilterForReason(
- PackageManagerService.REASON_INSTALL);
- } else {
- if (!DexFile.isValidCompilerFilter(compilerFilter)) {
- pw.println("Error: \"" + compilerFilter +
- "\" is not a valid compilation filter.");
- return 1;
- }
- targetCompilerFilter = compilerFilter;
+ if (!DexFile.isValidCompilerFilter(compilerFilter)) {
+ pw.println("Error: \"" + compilerFilter +
+ "\" is not a valid compilation filter.");
+ return 1;
}
+ targetCompilerFilter = compilerFilter;
} else {
int reason = -1;
for (int i = 0; i < PackageManagerServiceCompilerMapping.REASON_STRINGS.length; i++) {
@@ -1428,17 +1386,31 @@ class PackageManagerShellCommand extends ShellCommand {
pw.println(" help");
pw.println(" Print this help text.");
pw.println("");
- pw.println(" compile [-m MODE] [-f] [-c] [--reset] (-a | TARGET-PACKAGE)");
+ pw.println(" compile [-m MODE | -r REASON] [-f] [-c]");
+ pw.println(" [--reset] [--check-prof (true | false)] (-a | TARGET-PACKAGE)");
pw.println(" Trigger compilation of TARGET-PACKAGE or all packages if \"-a\".");
pw.println(" Options:");
pw.println(" -a: compile all packages");
pw.println(" -c: clear profile data before compiling");
pw.println(" -f: force compilation even if not needed");
pw.println(" -m: select compilation mode");
- pw.println(" MODE can be one of \"default\", \"full\", \"profile\"," +
- " and \"extract\"");
+ pw.println(" MODE is one of the dex2oat compiler filters:");
+ pw.println(" verify-none");
+ pw.println(" verify-at-runtime");
+ pw.println(" verify-profile");
+ pw.println(" interpret-only");
+ pw.println(" space-profile");
+ pw.println(" space");
+ pw.println(" speed-profile");
+ pw.println(" speed");
+ pw.println(" everything");
+ pw.println(" -r: select compilation reason");
+ pw.println(" REASON is one of:");
+ for (int i = 0; i < PackageManagerServiceCompilerMapping.REASON_STRINGS.length; i++) {
+ pw.println(" " + PackageManagerServiceCompilerMapping.REASON_STRINGS[i]);
+ }
pw.println(" --reset: restore package to its post-install state");
- pw.println(" shorthand for \"-c -f -m extract\"");
+ pw.println(" --check-prof (true | false): look at profiles when doing dexopt?");
pw.println(" list features");
pw.println(" Prints all features of the system.");
pw.println(" list instrumentation [-f] [TARGET-PACKAGE]");
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 2636d0959066..e409299c5378 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -3360,7 +3360,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
final int shiftlessModifiers = event.getModifiers() & ~KeyEvent.META_SHIFT_MASK;
if (KeyEvent.metaStateHasModifiers(shiftlessModifiers, KeyEvent.META_ALT_ON)) {
mRecentAppsHeldModifiers = shiftlessModifiers;
- showRecentApps(true);
+ showRecentApps(true, false);
return -1;
}
}
diff --git a/services/core/java/com/android/server/vr/VrManagerService.java b/services/core/java/com/android/server/vr/VrManagerService.java
index 844b5e6d5bfa..48c0feec4bdd 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.IVrStateCallbacks;
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 @@ public class VrManagerService extends SystemService implements EnabledComponentC
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 @@ public class VrManagerService extends SystemService implements EnabledComponentC
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 @@ public class VrManagerService extends SystemService implements EnabledComponentC
}
};
+ 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 @@ public class VrManagerService extends SystemService implements EnabledComponentC
@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 @@ public class VrManagerService extends SystemService implements EnabledComponentC
} 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 @@ public class VrManagerService extends SystemService implements EnabledComponentC
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 revokeCoarseLocationAccess(UserHandle userId) {
- PackageManager pm = mContext.getPackageManager();
- if (mPreviousCoarseLocationPackage != null) {
- pm.revokeRuntimePermission(mPreviousCoarseLocationPackage,
- android.Manifest.permission.ACCESS_COARSE_LOCATION, userId);
- mPreviousCoarseLocationPackage = null;
+ 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 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 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 revokeOverlayAccess(UserHandle userId) {
- PackageManager pm = mContext.getPackageManager();
- if (mPreviousManageOverlayPackage != null) {
- pm.revokeRuntimePermission(mPreviousManageOverlayPackage,
- android.Manifest.permission.SYSTEM_ALERT_WINDOW, userId);
- mPreviousManageOverlayPackage = null;
+ 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(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 @@ public class VrManagerService extends SystemService implements EnabledComponentC
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 @@ public class VrManagerService extends SystemService implements EnabledComponentC
}
}
- 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 49dab0a66815..a37b65ab9b64 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 @@ public class AppWindowAnimator {
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 805c986b1445..a23424175300 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.DEBUG_WINDOW_MOVEME
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 @@ class AppWindowToken extends WindowToken {
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 @@ class AppWindowToken extends WindowToken {
}
}
+ 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 @@ class AppWindowToken extends WindowToken {
// 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 @@ class AppWindowToken extends WindowToken {
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 @@ class AppWindowToken extends WindowToken {
win.destroyOrSaveSurface();
if (win.mRemoveOnExit) {
- win.mAnimatingExit = false;
service.removeWindowInnerLocked(win);
}
final DisplayContent displayContent = win.getDisplayContent();
@@ -388,43 +394,56 @@ class AppWindowToken extends WindowToken {
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 @@ class AppWindowToken extends WindowToken {
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 1fdc714dbf5a..fba439f8ca60 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 @@ class DisplayContent {
* 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 @@ class DisplayContent {
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 381449c16213..61425114ff9d 100644
--- a/services/core/java/com/android/server/wm/DockedStackDividerController.java
+++ b/services/core/java/com/android/server/wm/DockedStackDividerController.java
@@ -377,7 +377,14 @@ public class DockedStackDividerController implements DimLayerUser {
checkMinimizeChanged(true /* animate */);
}
+ boolean isMinimizedDock() {
+ return mMinimizedDock;
+ }
+
private void checkMinimizeChanged(boolean animate) {
+ if (mDisplayContent.getDockedStackVisibleForUserLocked() == null) {
+ return;
+ }
final TaskStack homeStack = mDisplayContent.getHomeStack();
if (homeStack == null) {
return;
@@ -412,8 +419,7 @@ public class DockedStackDividerController implements DimLayerUser {
private void setMinimizedDockedStack(boolean minimizedDock, boolean animate) {
final boolean wasMinimized = mMinimizedDock;
mMinimizedDock = minimizedDock;
- if (minimizedDock == wasMinimized
- || mDisplayContent.getDockedStackVisibleForUserLocked() == null) {
+ if (minimizedDock == wasMinimized) {
return;
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerDebugConfig.java b/services/core/java/com/android/server/wm/WindowManagerDebugConfig.java
index 5d3cc1694e29..f11281e7692f 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 @@ public class WindowManagerDebugConfig {
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 5a394d03f3ab..a0b8c356cdd8 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 @@ public class WindowManagerService extends IWindowManager.Stub
* 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 @@ public class WindowManagerService extends IWindowManager.Stub
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 @@ public class WindowManagerService extends IWindowManager.Stub
mTokenMap.remove(token.token);
} else if (atoken != null) {
atoken.firstWindowDrawn = false;
- atoken.allDrawn = false;
+ atoken.clearAllDrawn();
}
}
@@ -4423,6 +4423,7 @@ public class WindowManagerService extends IWindowManager.Stub
// 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 @@ public class WindowManagerService extends IWindowManager.Stub
// 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) {
@@ -6150,12 +6150,19 @@ public class WindowManagerService extends IWindowManager.Stub
WindowState appWin = null;
- boolean appIsImTarget;
+ boolean includeImeInScreenshot;
synchronized(mWindowMap) {
- appIsImTarget = mInputMethodTarget != null
- && mInputMethodTarget.mAppToken != null
- && mInputMethodTarget.mAppToken.appToken != null
- && mInputMethodTarget.mAppToken.appToken.asBinder() == appToken;
+ final AppWindowToken imeTargetAppToken =
+ mInputMethodTarget != null ? mInputMethodTarget.mAppToken : null;
+ // We only include the Ime in the screenshot if the app we are screenshoting is the IME
+ // target and isn't in multi-window mode. We don't screenshot the IME in multi-window
+ // mode because the frame of the IME might not overlap with that of the app.
+ // E.g. IME target app at the top in split-screen mode and the IME at the bottom
+ // overlapping with the bottom app.
+ includeImeInScreenshot = imeTargetAppToken != null
+ && imeTargetAppToken.appToken != null
+ && imeTargetAppToken.appToken.asBinder() == appToken
+ && !mInputMethodTarget.isInMultiWindowMode();
}
final int aboveAppLayer = (mPolicy.windowTypeToLayerLw(TYPE_APPLICATION) + 1)
@@ -6174,7 +6181,7 @@ public class WindowManagerService extends IWindowManager.Stub
continue;
}
if (ws.mIsImWindow) {
- if (!appIsImTarget) {
+ if (!includeImeInScreenshot) {
continue;
}
} else if (ws.mIsWallpaper) {
@@ -7527,6 +7534,7 @@ public class WindowManagerService extends IWindowManager.Stub
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:
@@ -7534,7 +7542,7 @@ public class WindowManagerService extends IWindowManager.Stub
// - 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);
@@ -9226,8 +9234,7 @@ public class WindowManagerService extends IWindowManager.Stub
}
winAnimator.mDrawState = DRAW_PENDING;
if (w.mAppToken != null) {
- w.mAppToken.allDrawn = false;
- w.mAppToken.deferClearAllDrawn = false;
+ w.mAppToken.clearAllDrawn();
}
}
if (!mResizingWindows.contains(w)) {
@@ -9384,7 +9391,7 @@ public class WindowManagerService extends IWindowManager.Stub
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 e73d547a7b87..b66de89f6a2d 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 @@ final class WindowState implements WindowManagerPolicy.WindowState {
// 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 @@ final class WindowState implements WindowManagerPolicy.WindowState {
// 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 @@ final class WindowState implements WindowManagerPolicy.WindowState {
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 @@ final class WindowState implements WindowManagerPolicy.WindowState {
}
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 @@ final class WindowState implements WindowManagerPolicy.WindowState {
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
@@ -1995,12 +2021,17 @@ final class WindowState implements WindowManagerPolicy.WindowState {
return mAppToken.shouldSaveSurface();
}
+ static final Region sEmptyRegion = new Region();
+
void destroyOrSaveSurface() {
mSurfaceSaved = shouldSaveSurface();
if (mSurfaceSaved) {
if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) {
Slog.v(TAG, "Saving surface: " + this);
}
+ // Previous user of the surface may have set a transparent region signaling a portion
+ // doesn't need to be composited, so reset to default empty state.
+ mSession.setTransparentRegion(mClient, sEmptyRegion);
mWinAnimator.hide("saved surface");
mWinAnimator.mDrawState = WindowStateAnimator.NO_SURFACE;
@@ -2014,18 +2045,22 @@ final class WindowState implements WindowManagerPolicy.WindowState {
} 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;
}
@@ -2033,6 +2068,7 @@ final class WindowState implements WindowManagerPolicy.WindowState {
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);
@@ -2045,10 +2081,30 @@ final class WindowState implements WindowManagerPolicy.WindowState {
}
}
- 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 a0784b5008db..f0bba4a952d5 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -322,6 +322,14 @@ class WindowStateAnimator {
return mAnimation != null;
}
+ /**
+ * Is this window currently waiting to run an opening animation?
+ */
+ boolean isWaitingForOpening() {
+ return mService.mAppTransition.isTransitionSet() && isDummyAnimation()
+ && mService.mOpeningApps.contains(mWin.mAppToken);
+ }
+
void cancelExitAnimationForNextAnimationLocked() {
if (DEBUG_ANIM) Slog.d(TAG,
"cancelExitAnimationForNextAnimationLocked: " + mWin);
@@ -576,14 +584,8 @@ class WindowStateAnimator {
+ 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 "
@@ -651,6 +653,13 @@ class WindowStateAnimator {
mDestroyPreservedSurfaceUponRedraw = false;
}
+ void markPreservedSurfaceForDestroy() {
+ if (mDestroyPreservedSurfaceUponRedraw
+ && !mService.mDestroyPreservedSurface.contains(mWin)) {
+ mService.mDestroyPreservedSurface.add(mWin);
+ }
+ }
+
WindowSurfaceController createSurfaceLocked() {
final WindowState w = mWin;
if (w.hasSavedSurface()) {
@@ -672,8 +681,7 @@ class WindowStateAnimator {
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.
@@ -825,20 +833,19 @@ class WindowStateAnimator {
}
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;
@@ -1448,8 +1455,7 @@ class WindowStateAnimator {
// the same app again before the app's surface is destroyed or saved, the surface
// is always ready in the whole process.) If we go ahead here, the opening app
// will be shown with the full size before the correct animation spec arrives.
- if (mService.mAppTransition.isTransitionSet() && isDummyAnimation() &&
- mService.mOpeningApps.contains(w.mAppToken)) {
+ if (isWaitingForOpening()) {
return;
}
@@ -1511,9 +1517,7 @@ class WindowStateAnimator {
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/core/java/com/android/server/wm/WindowSurfacePlacer.java b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
index fb4be303ced3..e20e245aa574 100644
--- a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
+++ b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
@@ -772,7 +772,7 @@ class WindowSurfacePlacer {
}
}
}
- if (!winAnimator.isAnimationStarting()) {
+ if (!winAnimator.isAnimationStarting() && !winAnimator.isWaitingForOpening()) {
// Updates the shown frame before we set up the surface. This is needed
// because the resizing could change the top-left position (in addition to
// size) of the window. setSurfaceBoundariesLocked uses mShownPosition to
@@ -1236,8 +1236,8 @@ class WindowSurfacePlacer {
int topOpeningLayer = 0;
if (animLp != null) {
int layer = -1;
- for (int j = 0; j < wtoken.windows.size(); j++) {
- final WindowState win = wtoken.windows.get(j);
+ for (int j = 0; j < wtoken.allAppWindows.size(); j++) {
+ final WindowState win = wtoken.allAppWindows.get(j);
// Clearing the mAnimatingExit flag before entering animation. It will be set to true
// if app window is removed, or window relayout to invisible. We don't want to
// clear it out for windows that get replaced, because the animation depends on
@@ -1249,6 +1249,14 @@ class WindowSurfacePlacer {
// they won't eventually be removed by WindowStateAnimator#finishExit.
if (!win.mWillReplaceWindow && !win.mRemoveOnExit) {
win.mAnimatingExit = false;
+ // Clear mAnimating flag together with mAnimatingExit. When animation
+ // changes from exiting to entering, we need to clear this flag until the
+ // new animation gets applied, so that isAnimationStarting() becomes true
+ // until then.
+ // Otherwise applySurfaceChangesTransaction will faill to skip surface
+ // placement for this window during this period, one or more frame will
+ // show up with wrong position or scale.
+ win.mWinAnimator.mAnimating = false;
}
if (win.mWinAnimator.mAnimLayer > layer) {
layer = win.mWinAnimator.mAnimLayer;
diff --git a/services/midi/java/com/android/server/midi/MidiService.java b/services/midi/java/com/android/server/midi/MidiService.java
index 723be2481d6f..1c18c9b091b7 100644
--- a/services/midi/java/com/android/server/midi/MidiService.java
+++ b/services/midi/java/com/android/server/midi/MidiService.java
@@ -41,6 +41,7 @@ import android.os.Bundle;
import android.os.IBinder;
import android.os.Process;
import android.os.RemoteException;
+import android.os.UserHandle;
import android.util.Log;
import com.android.internal.content.PackageMonitor;
@@ -71,6 +72,13 @@ public class MidiService extends IMidiManager.Stub {
mMidiService = new MidiService(getContext());
publishBinderService(Context.MIDI_SERVICE, mMidiService);
}
+
+ @Override
+ public void onUnlockUser(int userHandle) {
+ if (userHandle == UserHandle.USER_SYSTEM) {
+ mMidiService.onUnlockUser();
+ }
+ }
}
private static final String TAG = "MidiService";
@@ -97,7 +105,7 @@ public class MidiService extends IMidiManager.Stub {
private final PackageManager mPackageManager;
// UID of BluetoothMidiService
- private final int mBluetoothServiceUid;
+ private int mBluetoothServiceUid;
// PackageMonitor for listening to package changes
private final PackageMonitor mPackageMonitor = new PackageMonitor() {
@@ -557,7 +565,12 @@ public class MidiService extends IMidiManager.Stub {
public MidiService(Context context) {
mContext = context;
mPackageManager = context.getPackageManager();
- mPackageMonitor.register(context, null, true);
+
+ mBluetoothServiceUid = -1;
+ }
+
+ private void onUnlockUser() {
+ mPackageMonitor.register(mContext, null, true);
Intent intent = new Intent(MidiDeviceService.SERVICE_INTERFACE);
List<ResolveInfo> resolveInfos = mPackageManager.queryIntentServices(intent,
@@ -583,7 +596,7 @@ public class MidiService extends IMidiManager.Stub {
} else {
mBluetoothServiceUid = -1;
}
- }
+ }
@Override
public void registerListener(IBinder token, IMidiDeviceListener listener) {
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 cff5876f858e..21560acbf3bb 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.IdleableHandlerThread;
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 @@ public class NetworkStatsObserversTest extends TestCase {
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 class NetworkStatsObserversTest extends TestCase {
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 class NetworkStatsObserversTest extends TestCase {
}
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 class NetworkStatsObserversTest extends TestCase {
}
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 class NetworkStatsObserversTest extends TestCase {
}
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 @@ public class NetworkStatsObserversTest extends TestCase {
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 @@ public class NetworkStatsObserversTest extends TestCase {
assertEquals(NetworkStatsManager.CALLBACK_LIMIT_REACHED, mHandler.mLastMessageType);
}
- public void testUpdateStats_aboveThresholdMultipleNetwork_notifies() throws Exception {
- NetworkTemplate[] templates = new NetworkTemplate[] { sTemplateImsi1, sTemplateImsi2 };
- 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 };
+ public void testUpdateStats_defaultAccess_notifiesSameUid() 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_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 @@ public class NetworkStatsObserversTest extends TestCase {
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 @@ public class NetworkStatsObserversTest extends TestCase {
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 @@ public class NetworkStatsObserversTest extends TestCase {
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 class NetworkStatsObserversTest extends TestCase {
}
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 @@ public class NetworkStatsObserversTest extends TestCase {
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 class NetworkStatsObserversTest extends TestCase {
}
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 @@ public class NetworkStatsObserversTest extends TestCase {
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 74c19845cd00..94c6711da9ae 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 org.easymock.EasyMock;
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 class NetworkStatsServiceTest extends AndroidTestCase {
}
- 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 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
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 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
// 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 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
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 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
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();
-
- 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 {
+ 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 };
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/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
index 27351e42d5c5..0694911461e0 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
@@ -251,7 +251,8 @@ final class VoiceInteractionSessionConnection implements ServiceConnection {
&& structureEnabled) {
mAssistData.clear();
final int count = activityToken != null ? 1 : topActivities.size();
- for (int i = 0; i < count; i++) {
+ // Temp workaround for bug: 28348867 Revert after DP3
+ for (int i = 0; i < count && i < 1; i++) {
IBinder topActivity = count == 1 ? activityToken : topActivities.get(i);
try {
MetricsLogger.count(mContext, "assist_with_context", 1);
@@ -259,7 +260,8 @@ final class VoiceInteractionSessionConnection implements ServiceConnection {
receiverExtras.putInt(KEY_RECEIVER_EXTRA_INDEX, i);
receiverExtras.putInt(KEY_RECEIVER_EXTRA_COUNT, count);
if (mAm.requestAssistContextExtras(ActivityManager.ASSIST_CONTEXT_FULL,
- mAssistReceiver, receiverExtras, topActivity, i == 0)) {
+ mAssistReceiver, receiverExtras, topActivity,
+ /* focused= */ i == 0, /* newSessionId= */ i == 0)) {
needDisclosure = true;
mPendingAssistDataCount++;
} else if (i == 0) {
diff --git a/tests/UiBench/AndroidManifest.xml b/tests/UiBench/AndroidManifest.xml
index 7b4f01cad849..95bbb2139a95 100644
--- a/tests/UiBench/AndroidManifest.xml
+++ b/tests/UiBench/AndroidManifest.xml
@@ -161,5 +161,16 @@
<category android:name="com.android.test.uibench.TEST" />
</intent-filter>
</activity>
+
+ <!-- WebView -->
+ <activity
+ android:name=".ScrollableWebViewActivity"
+ android:label="WebView/Scrollable WebView" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="com.android.test.uibench.TEST" />
+ </intent-filter>
+ </activity>
+
</application>
</manifest>
diff --git a/tests/UiBench/src/com/android/test/uibench/ScrollableWebViewActivity.java b/tests/UiBench/src/com/android/test/uibench/ScrollableWebViewActivity.java
new file mode 100644
index 000000000000..02c2a0898cdd
--- /dev/null
+++ b/tests/UiBench/src/com/android/test/uibench/ScrollableWebViewActivity.java
@@ -0,0 +1,35 @@
+/*
+ * 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.test.uibench;
+
+import android.os.Bundle;
+import android.support.v7.app.AppCompatActivity;
+import android.webkit.WebView;
+
+public class ScrollableWebViewActivity extends AppCompatActivity {
+ static String sHtml = "<body style=\"height:10000px;"
+ + "background:repeating-linear-gradient(white, black 10%)\"/>";
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ WebView webView = new WebView(this);
+ webView.loadData(sHtml, "text/html", null);
+ webView.setVerticalScrollBarEnabled(true);
+ setContentView(webView);
+ }
+}
diff --git a/tools/fonts/fontchain_lint.py b/tools/fonts/fontchain_lint.py
index fe7c3b9b400f..ea36e2cb0d6a 100755
--- a/tools/fonts/fontchain_lint.py
+++ b/tools/fonts/fontchain_lint.py
@@ -412,8 +412,9 @@ def parse_ucd(ucd_path):
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: