summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--api/current.txt1
-rw-r--r--api/system-current.txt1
-rw-r--r--api/test-current.txt1
-rw-r--r--cmds/bootanimation/BootAnimation.cpp7
-rw-r--r--core/java/android/app/ActivityManager.java8
-rw-r--r--core/java/android/app/ApplicationErrorReport.java25
-rw-r--r--core/java/android/app/WallpaperManager.java36
-rw-r--r--core/java/android/app/admin/DevicePolicyManager.java24
-rw-r--r--core/java/android/app/admin/IDevicePolicyManager.aidl2
-rw-r--r--core/java/android/content/pm/ShortcutServiceInternal.java7
-rw-r--r--core/java/android/hardware/location/ContextHubService.java80
-rw-r--r--core/java/android/net/LinkAddress.java2
-rw-r--r--core/java/android/os/UserManager.java11
-rwxr-xr-xcore/java/android/provider/Settings.java9
-rw-r--r--core/java/android/service/notification/ZenModeConfig.java77
-rw-r--r--core/java/android/view/IWindowManager.aidl5
-rw-r--r--core/java/android/view/View.java3
-rw-r--r--core/java/android/view/ViewRootImpl.java21
-rw-r--r--core/java/com/android/internal/widget/LockPatternUtils.java9
-rw-r--r--core/jni/android_hardware_location_ContextHubService.cpp594
-rw-r--r--core/res/res/values/config.xml8
-rw-r--r--core/res/res/values/symbols.xml6
-rw-r--r--docs/html/_redirects.yaml6
-rw-r--r--docs/html/distribute/stories/apps.jd2
-rw-r--r--docs/html/distribute/stories/apps/aftenposten.jd80
-rw-r--r--docs/html/distribute/stories/apps/el-mundo.jd73
-rw-r--r--docs/html/distribute/stories/apps/segundamano.jd63
-rw-r--r--docs/html/distribute/stories/apps/tapps.jd366
-rw-r--r--docs/html/distribute/stories/apps/upbeat-games.jd69
-rw-r--r--docs/html/images/cards/distribute/stories/aftenposten.pngbin0 -> 7948 bytes
-rw-r--r--docs/html/images/cards/distribute/stories/el-mundo.pngbin0 -> 9092 bytes
-rw-r--r--docs/html/images/cards/distribute/stories/segundamano.pngbin0 -> 14540 bytes
-rw-r--r--docs/html/images/cards/distribute/stories/tapps.pngbin0 -> 11603 bytes
-rw-r--r--docs/html/images/cards/distribute/stories/witch-puzzle.pngbin0 -> 31043 bytes
-rw-r--r--docs/html/images/distribute/stories/aftenposten-icon.pngbin0 -> 7948 bytes
-rw-r--r--docs/html/images/distribute/stories/el-mundo-icon.pngbin0 -> 9092 bytes
-rw-r--r--docs/html/images/distribute/stories/japanese-witch-puzzle.pngbin0 -> 94261 bytes
-rw-r--r--docs/html/images/distribute/stories/segundamano-icon.pngbin0 -> 14540 bytes
-rw-r--r--docs/html/images/distribute/stories/tapps-candy-hills.pngbin0 -> 357502 bytes
-rw-r--r--docs/html/images/distribute/stories/tapps-icon-orig-1.pngbin0 -> 33454 bytes
-rw-r--r--docs/html/images/distribute/stories/tapps-icon-orig-2.pngbin0 -> 47461 bytes
-rw-r--r--docs/html/images/distribute/stories/tapps-icon-orig-3.pngbin0 -> 24568 bytes
-rw-r--r--docs/html/images/distribute/stories/tapps-icon-var-1-2.pngbin0 -> 27740 bytes
-rw-r--r--docs/html/images/distribute/stories/tapps-icon-var-1.pngbin0 -> 40198 bytes
-rw-r--r--docs/html/images/distribute/stories/tapps-icon-var-2-2.pngbin0 -> 46349 bytes
-rw-r--r--docs/html/images/distribute/stories/tapps-icon-var-2.pngbin0 -> 47518 bytes
-rw-r--r--docs/html/images/distribute/stories/tapps-icon-var-3-2.pngbin0 -> 16998 bytes
-rw-r--r--docs/html/images/distribute/stories/tapps-icon-var-3.pngbin0 -> 17868 bytes
-rw-r--r--docs/html/images/distribute/stories/tapps-logic-pic.pngbin0 -> 18349 bytes
-rw-r--r--docs/html/images/distribute/stories/tapps-logo.pngbin0 -> 11603 bytes
-rw-r--r--docs/html/images/distribute/stories/tapps-screen-orig-1.pngbin0 -> 109993 bytes
-rw-r--r--docs/html/images/distribute/stories/tapps-screen-orig-2.pngbin0 -> 638813 bytes
-rw-r--r--docs/html/images/distribute/stories/tapps-screen-orig-3.pngbin0 -> 279975 bytes
-rw-r--r--docs/html/images/distribute/stories/tapps-screen-var-1.pngbin0 -> 861604 bytes
-rw-r--r--docs/html/images/distribute/stories/tapps-screen-var-2.pngbin0 -> 522603 bytes
-rw-r--r--docs/html/images/distribute/stories/tapps-screen-var-3.pngbin0 -> 358402 bytes
-rw-r--r--docs/html/images/distribute/stories/tapps-villains-corp.pngbin0 -> 43911 bytes
-rw-r--r--docs/html/images/distribute/stories/witch-puzzle-icon.pngbin0 -> 31043 bytes
-rw-r--r--docs/html/topic/performance/index.jd2
-rw-r--r--docs/html/topic/performance/launch-time.jd4
-rw-r--r--libs/hwui/PropertyValuesAnimatorSet.h4
-rw-r--r--location/java/android/location/GnssMeasurementsEvent.java8
-rw-r--r--media/java/android/media/AudioFormat.java1
-rw-r--r--media/java/android/media/MediaPlayer.java2
-rw-r--r--media/java/android/media/PlayerBase.java7
-rw-r--r--media/java/android/media/SoundPool.java36
-rw-r--r--media/java/android/media/soundtrigger/SoundTriggerDetector.java11
-rw-r--r--media/jni/android_media_MediaDataSource.cpp5
-rw-r--r--media/jni/android_media_MediaDataSource.h1
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/SaveFragment.java9
-rw-r--r--packages/PrintSpooler/res/drawable/print_button.xml2
-rw-r--r--packages/PrintSpooler/res/values/colors.xml2
-rw-r--r--packages/SettingsProvider/res/values/defaults.xml3
-rw-r--r--packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java59
-rw-r--r--packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml2
-rw-r--r--packages/SystemUI/res/values/dimens.xml2
-rw-r--r--packages/SystemUI/src/com/android/systemui/assist/AssistManager.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonDispatcher.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java32
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java24
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java32
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/ReverseLinearLayout.java45
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java24
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/ZenFooter.java8
-rw-r--r--packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java103
-rw-r--r--proto/src/metrics_constants.proto419
-rw-r--r--services/backup/java/com/android/server/backup/BackupManagerService.java109
-rw-r--r--services/core/java/com/android/server/AlarmManagerService.java4
-rw-r--r--services/core/java/com/android/server/AnyMotionDetector.java78
-rw-r--r--services/core/java/com/android/server/DeviceIdleController.java7
-rw-r--r--services/core/java/com/android/server/PersistentDataBlockService.java19
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java27
-rw-r--r--services/core/java/com/android/server/am/ActivityStack.java8
-rw-r--r--services/core/java/com/android/server/am/ActivityStackSupervisor.java25
-rw-r--r--services/core/java/com/android/server/am/AppErrors.java73
-rw-r--r--services/core/java/com/android/server/connectivity/Tethering.java5
-rw-r--r--services/core/java/com/android/server/connectivity/tethering/IPv6TetheringCoordinator.java253
-rw-r--r--services/core/java/com/android/server/connectivity/tethering/IPv6TetheringInterfaceServices.java177
-rw-r--r--services/core/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachine.java23
-rw-r--r--services/core/java/com/android/server/media/MediaSessionRecord.java2
-rw-r--r--services/core/java/com/android/server/media/MediaSessionService.java145
-rw-r--r--services/core/java/com/android/server/media/MediaSessionStack.java42
-rw-r--r--services/core/java/com/android/server/notification/NotificationManagerService.java4
-rw-r--r--services/core/java/com/android/server/notification/ZenModeHelper.java16
-rw-r--r--services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java2
-rw-r--r--services/core/java/com/android/server/pm/PackageInstallerService.java40
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java15
-rw-r--r--services/core/java/com/android/server/pm/ShortcutPackage.java4
-rw-r--r--services/core/java/com/android/server/pm/ShortcutPendingTasks.java159
-rw-r--r--services/core/java/com/android/server/pm/ShortcutService.java198
-rw-r--r--services/core/java/com/android/server/pm/UserManagerService.java17
-rw-r--r--services/core/java/com/android/server/pm/UserRestrictionsUtils.java7
-rw-r--r--services/core/java/com/android/server/policy/ImmersiveModeConfirmation.java8
-rw-r--r--services/core/java/com/android/server/policy/PhoneWindowManager.java49
-rw-r--r--services/core/java/com/android/server/vr/EnabledComponentsObserver.java4
-rw-r--r--services/core/java/com/android/server/wallpaper/WallpaperManagerService.java25
-rw-r--r--services/core/java/com/android/server/wm/AppTransition.java5
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java88
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java33
-rw-r--r--services/retaildemo/java/com/android/server/retaildemo/RetailDemoModeService.java9
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java27
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java375
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest3.java2
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/ShortcutPendingTasksTest.java123
-rw-r--r--tests/SoundTriggerTestApp/src/com/android/test/soundtrigger/SoundTriggerTestService.java8
-rw-r--r--tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java5
128 files changed, 3183 insertions, 1504 deletions
diff --git a/api/current.txt b/api/current.txt
index d5f36bdb081f..d3ee682370b9 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -19652,6 +19652,7 @@ package android.media {
field public static final android.os.Parcelable.Creator<android.media.AudioFormat> CREATOR;
field public static final int ENCODING_AC3 = 5; // 0x5
field public static final int ENCODING_DEFAULT = 1; // 0x1
+ field public static final int ENCODING_DOLBY_TRUEHD = 14; // 0xe
field public static final int ENCODING_DTS = 7; // 0x7
field public static final int ENCODING_DTS_HD = 8; // 0x8
field public static final int ENCODING_E_AC3 = 6; // 0x6
diff --git a/api/system-current.txt b/api/system-current.txt
index 16c75cc5d747..13ad2d666dcb 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -21160,6 +21160,7 @@ package android.media {
field public static final android.os.Parcelable.Creator<android.media.AudioFormat> CREATOR;
field public static final int ENCODING_AC3 = 5; // 0x5
field public static final int ENCODING_DEFAULT = 1; // 0x1
+ field public static final int ENCODING_DOLBY_TRUEHD = 14; // 0xe
field public static final int ENCODING_DTS = 7; // 0x7
field public static final int ENCODING_DTS_HD = 8; // 0x8
field public static final int ENCODING_E_AC3 = 6; // 0x6
diff --git a/api/test-current.txt b/api/test-current.txt
index 7fdbb6411ef4..c6359dd4d1e9 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -19722,6 +19722,7 @@ package android.media {
field public static final android.os.Parcelable.Creator<android.media.AudioFormat> CREATOR;
field public static final int ENCODING_AC3 = 5; // 0x5
field public static final int ENCODING_DEFAULT = 1; // 0x1
+ field public static final int ENCODING_DOLBY_TRUEHD = 14; // 0xe
field public static final int ENCODING_DTS = 7; // 0x7
field public static final int ENCODING_DTS_HD = 8; // 0x8
field public static final int ENCODING_E_AC3 = 6; // 0x6
diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp
index d82629d3a4b4..4098772bba12 100644
--- a/cmds/bootanimation/BootAnimation.cpp
+++ b/cmds/bootanimation/BootAnimation.cpp
@@ -72,6 +72,8 @@ static const char LAST_TIME_CHANGED_FILE_NAME[] = "last_time_change";
static const char LAST_TIME_CHANGED_FILE_PATH[] = "/data/system/time/last_time_change";
static const char ACCURATE_TIME_FLAG_FILE_NAME[] = "time_is_accurate";
static const char ACCURATE_TIME_FLAG_FILE_PATH[] = "/data/system/time/time_is_accurate";
+// Java timestamp format. Don't show the clock if the date is before 2000-01-01 00:00:00.
+static const long long ACCURATE_TIME_EPOCH = 946684800000;
static const char EXIT_PROP_NAME[] = "service.bootanim.exit";
static const int ANIM_ENTRY_NAME_MAX = 256;
@@ -932,8 +934,9 @@ bool BootAnimation::updateIsTimeAccurate() {
clock_gettime(CLOCK_REALTIME, &now);
// Match the Java timestamp format
long long rtcNow = (now.tv_sec * 1000LL) + (now.tv_nsec / 1000000LL);
- if (lastChangedTime > rtcNow - MAX_TIME_IN_PAST
- && lastChangedTime < rtcNow + MAX_TIME_IN_FUTURE) {
+ if (ACCURATE_TIME_EPOCH < rtcNow
+ && lastChangedTime > (rtcNow - MAX_TIME_IN_PAST)
+ && lastChangedTime < (rtcNow + MAX_TIME_IN_FUTURE)) {
mTimeIsAccurate = true;
}
}
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 23fea7133015..af981f69d3b6 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -93,7 +93,8 @@ public class ActivityManager {
@IntDef({
BUGREPORT_OPTION_FULL,
BUGREPORT_OPTION_INTERACTIVE,
- BUGREPORT_OPTION_REMOTE
+ BUGREPORT_OPTION_REMOTE,
+ BUGREPORT_OPTION_WEAR
})
public @interface BugreportMode {}
/**
@@ -114,6 +115,11 @@ public class ActivityManager {
* @hide
*/
public static final int BUGREPORT_OPTION_REMOTE = 2;
+ /**
+ * Takes a bugreport on a wearable device.
+ * @hide
+ */
+ public static final int BUGREPORT_OPTION_WEAR = 3;
/**
* <a href="{@docRoot}guide/topics/manifest/meta-data-element.html">{@code
diff --git a/core/java/android/app/ApplicationErrorReport.java b/core/java/android/app/ApplicationErrorReport.java
index 8692336439f9..9fa8a5d2faee 100644
--- a/core/java/android/app/ApplicationErrorReport.java
+++ b/core/java/android/app/ApplicationErrorReport.java
@@ -345,7 +345,7 @@ public class ApplicationErrorReport implements Parcelable {
PrintWriter pw = new FastPrintWriter(sw, false, 256);
tr.printStackTrace(pw);
pw.flush();
- stackTrace = sw.toString();
+ stackTrace = sanitizeString(sw.toString());
exceptionMessage = tr.getMessage();
// Populate fields with the "root cause" exception
@@ -374,6 +374,29 @@ public class ApplicationErrorReport implements Parcelable {
throwMethodName = "unknown";
throwLineNumber = 0;
}
+
+ exceptionMessage = sanitizeString(exceptionMessage);
+ }
+
+ /**
+ * Ensure that the string is of reasonable size, truncating from the middle if needed.
+ */
+ private String sanitizeString(String s) {
+ int prefixLength = 10 * 1024;
+ int suffixLength = 10 * 1024;
+ int acceptableLength = prefixLength + suffixLength;
+
+ if (s != null && s.length() > acceptableLength) {
+ String replacement =
+ "\n[TRUNCATED " + (s.length() - acceptableLength) + " CHARS]\n";
+
+ StringBuilder sb = new StringBuilder(acceptableLength + replacement.length());
+ sb.append(s.substring(0, prefixLength));
+ sb.append(replacement);
+ sb.append(s.substring(s.length() - suffixLength));
+ return sb.toString();
+ }
+ return s;
}
/**
diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java
index 79f2a1e90c0a..53da4e32eb8a 100644
--- a/core/java/android/app/WallpaperManager.java
+++ b/core/java/android/app/WallpaperManager.java
@@ -266,7 +266,7 @@ public class WallpaperManager {
}
static class Globals extends IWallpaperManagerCallback.Stub {
- private IWallpaperManager mService;
+ private final IWallpaperManager mService;
private Bitmap mCachedWallpaper;
private int mCachedWallpaperUserId;
private Bitmap mDefaultWallpaper;
@@ -293,16 +293,16 @@ public class WallpaperManager {
public Bitmap peekWallpaperBitmap(Context context, boolean returnDefault,
@SetWallpaperFlags int which, int userId) {
- synchronized (this) {
- if (mService != null) {
- try {
- if (!mService.isWallpaperSupported(context.getOpPackageName())) {
- return null;
- }
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
+ if (mService != null) {
+ try {
+ if (!mService.isWallpaperSupported(context.getOpPackageName())) {
+ return null;
}
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
+ }
+ synchronized (this) {
if (mCachedWallpaper != null && mCachedWallpaperUserId == userId) {
return mCachedWallpaper;
}
@@ -317,17 +317,21 @@ public class WallpaperManager {
if (mCachedWallpaper != null) {
return mCachedWallpaper;
}
- if (returnDefault) {
- if (mDefaultWallpaper == null) {
- mDefaultWallpaper = getDefaultWallpaperLocked(context, which);
+ }
+ if (returnDefault) {
+ Bitmap defaultWallpaper = mDefaultWallpaper;
+ if (defaultWallpaper == null) {
+ defaultWallpaper = getDefaultWallpaper(context, which);
+ synchronized (this) {
+ mDefaultWallpaper = defaultWallpaper;
}
- return mDefaultWallpaper;
}
- return null;
+ return defaultWallpaper;
}
+ return null;
}
- public void forgetLoadedWallpaper() {
+ void forgetLoadedWallpaper() {
synchronized (this) {
mCachedWallpaper = null;
mCachedWallpaperUserId = 0;
@@ -362,7 +366,7 @@ public class WallpaperManager {
return null;
}
- private Bitmap getDefaultWallpaperLocked(Context context, @SetWallpaperFlags int which) {
+ private Bitmap getDefaultWallpaper(Context context, @SetWallpaperFlags int which) {
InputStream is = openDefaultWallpaper(context, which);
if (is != null) {
try {
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 97f936afee99..dc33671a4260 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -6436,6 +6436,30 @@ public class DevicePolicyManager {
}
}
+ /**
+ * @hide
+ * Writes that the provisioning configuration has been applied.
+ */
+ public void setDeviceProvisioningConfigApplied() {
+ try {
+ mService.setDeviceProvisioningConfigApplied();
+ } catch (RemoteException re) {
+ throw re.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * @hide
+ * @return whether the provisioning configuration has been applied.
+ */
+ public boolean isDeviceProvisioningConfigApplied() {
+ try {
+ return mService.isDeviceProvisioningConfigApplied();
+ } catch (RemoteException re) {
+ throw re.rethrowFromSystemServer();
+ }
+ }
+
private void throwIfParentInstance(String functionName) {
if (mParentInstance) {
throw new SecurityException(functionName + " cannot be called on the parent instance");
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 4b793d15753a..1036f0499a54 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -303,4 +303,6 @@ interface IDevicePolicyManager {
void uninstallPackageWithActiveAdmins(String packageName);
boolean isDeviceProvisioned();
+ boolean isDeviceProvisioningConfigApplied();
+ void setDeviceProvisioningConfigApplied();
}
diff --git a/core/java/android/content/pm/ShortcutServiceInternal.java b/core/java/android/content/pm/ShortcutServiceInternal.java
index de52f73fc213..3f8bad15035b 100644
--- a/core/java/android/content/pm/ShortcutServiceInternal.java
+++ b/core/java/android/content/pm/ShortcutServiceInternal.java
@@ -73,11 +73,4 @@ public abstract class ShortcutServiceInternal {
* any locks in this method.
*/
public abstract void onSystemLocaleChangedNoLock();
-
- /**
- * Called by PM before sending package broadcasts to other components. PM doesn't hold the PM
- * lock, but do not take any locks in here anyway, and don't do any heavy tasks, as doing so
- * would slow down all the package broadcasts.
- */
- public abstract void onPackageBroadcast(Intent intent);
}
diff --git a/core/java/android/hardware/location/ContextHubService.java b/core/java/android/hardware/location/ContextHubService.java
index 43e596fe5566..fcbc962f0743 100644
--- a/core/java/android/hardware/location/ContextHubService.java
+++ b/core/java/android/hardware/location/ContextHubService.java
@@ -16,6 +16,11 @@
package android.hardware.location;
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.HashMap;
+
import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
@@ -53,10 +58,14 @@ public class ContextHubService extends IContextHubService.Stub {
private static final int PRE_LOADED_APP_MEM_REQ = 0;
private static final int MSG_HEADER_SIZE = 4;
- private static final int MSG_FIELD_TYPE = 0;
- private static final int MSG_FIELD_VERSION = 1;
- private static final int MSG_FIELD_HUB_HANDLE = 2;
- private static final int MSG_FIELD_APP_INSTANCE = 3;
+ private static final int HEADER_FIELD_MSG_TYPE = 0;
+ private static final int HEADER_FIELD_MSG_VERSION = 1;
+ private static final int HEADER_FIELD_HUB_HANDLE = 2;
+ private static final int HEADER_FIELD_APP_INSTANCE = 3;
+
+ private static final int HEADER_FIELD_LOAD_APP_ID_LO = MSG_HEADER_SIZE;
+ private static final int HEADER_FIELD_LOAD_APP_ID_HI = MSG_HEADER_SIZE + 1;
+ private static final int MSG_LOAD_APP_HEADER_SIZE = MSG_HEADER_SIZE + 2;
private static final int OS_APP_INSTANCE = -1;
@@ -146,11 +155,16 @@ public class ContextHubService extends IContextHubService.Stub {
return -1;
}
- int[] msgHeader = new int[MSG_HEADER_SIZE];
- msgHeader[MSG_FIELD_HUB_HANDLE] = contextHubHandle;
- msgHeader[MSG_FIELD_APP_INSTANCE] = OS_APP_INSTANCE;
- msgHeader[MSG_FIELD_VERSION] = 0;
- msgHeader[MSG_FIELD_TYPE] = MSG_LOAD_NANO_APP;
+ int[] msgHeader = new int[MSG_LOAD_APP_HEADER_SIZE];
+ msgHeader[HEADER_FIELD_HUB_HANDLE] = contextHubHandle;
+ msgHeader[HEADER_FIELD_APP_INSTANCE] = OS_APP_INSTANCE;
+ msgHeader[HEADER_FIELD_MSG_VERSION] = 0;
+ msgHeader[HEADER_FIELD_MSG_TYPE] = MSG_LOAD_NANO_APP;
+
+ long appId = app.getAppId();
+
+ msgHeader[HEADER_FIELD_LOAD_APP_ID_LO] = (int)(appId & 0xFFFFFFFF);
+ msgHeader[HEADER_FIELD_LOAD_APP_ID_HI] = (int)((appId >> 32) & 0xFFFFFFFF);
if (nativeSendMessage(msgHeader, app.getAppBinary()) != 0) {
return -1;
@@ -169,12 +183,14 @@ public class ContextHubService extends IContextHubService.Stub {
// Call Native interface here
int[] msgHeader = new int[MSG_HEADER_SIZE];
- msgHeader[MSG_FIELD_HUB_HANDLE] = ANY_HUB;
- msgHeader[MSG_FIELD_APP_INSTANCE] = OS_APP_INSTANCE;
- msgHeader[MSG_FIELD_VERSION] = 0;
- msgHeader[MSG_FIELD_TYPE] = MSG_UNLOAD_NANO_APP;
+ msgHeader[HEADER_FIELD_HUB_HANDLE] = ANY_HUB;
+ msgHeader[HEADER_FIELD_APP_INSTANCE] = nanoAppInstanceHandle;
+ msgHeader[HEADER_FIELD_MSG_VERSION] = 0;
+ msgHeader[HEADER_FIELD_MSG_TYPE] = MSG_UNLOAD_NANO_APP;
- if (nativeSendMessage(msgHeader, null) != 0) {
+ byte msg[] = new byte[0];
+
+ if (nativeSendMessage(msgHeader, msg) != 0) {
return -1;
}
@@ -222,10 +238,10 @@ public class ContextHubService extends IContextHubService.Stub {
checkPermissions();
int[] msgHeader = new int[MSG_HEADER_SIZE];
- msgHeader[MSG_FIELD_HUB_HANDLE] = hubHandle;
- msgHeader[MSG_FIELD_APP_INSTANCE] = nanoAppHandle;
- msgHeader[MSG_FIELD_VERSION] = msg.getVersion();
- msgHeader[MSG_FIELD_TYPE] = msg.getMsgType();
+ msgHeader[HEADER_FIELD_HUB_HANDLE] = hubHandle;
+ msgHeader[HEADER_FIELD_APP_INSTANCE] = nanoAppHandle;
+ msgHeader[HEADER_FIELD_MSG_VERSION] = msg.getVersion();
+ msgHeader[HEADER_FIELD_MSG_TYPE] = msg.getMsgType();
return nativeSendMessage(msgHeader, msg.getData());
}
@@ -269,15 +285,17 @@ public class ContextHubService extends IContextHubService.Stub {
Log.v(TAG, "No message callbacks registered.");
return 0;
}
- ContextHubMessage message =
- new ContextHubMessage(header[MSG_FIELD_TYPE], header[MSG_FIELD_VERSION], data);
+
+ ContextHubMessage msg = new ContextHubMessage(header[HEADER_FIELD_MSG_TYPE],
+ header[HEADER_FIELD_MSG_VERSION],
+ data);
for (int i = 0; i < callbacksCount; ++i) {
IContextHubCallback callback = mCallbacksList.getBroadcastItem(i);
try {
callback.onMessageReceipt(
- header[MSG_FIELD_HUB_HANDLE],
- header[MSG_FIELD_APP_INSTANCE],
- message);
+ header[HEADER_FIELD_HUB_HANDLE],
+ header[HEADER_FIELD_APP_INSTANCE],
+ msg);
} catch (RemoteException e) {
Log.i(TAG, "Exception (" + e + ") calling remote callback (" + callback + ").");
continue;
@@ -308,12 +326,20 @@ public class ContextHubService extends IContextHubService.Stub {
return 0;
}
+ private int deleteAppInstance(int appInstanceHandle) {
+ if (mNanoAppHash.remove(appInstanceHandle) == null) {
+ return -1;
+ }
+
+ return 0;
+ }
+
private void sendVrStateChangeMessageToApp(NanoAppInstanceInfo app, boolean vrModeEnabled) {
int[] msgHeader = new int[MSG_HEADER_SIZE];
- msgHeader[MSG_FIELD_TYPE] = 0;
- msgHeader[MSG_FIELD_VERSION] = 0;
- msgHeader[MSG_FIELD_HUB_HANDLE] = ANY_HUB;
- msgHeader[MSG_FIELD_APP_INSTANCE] = app.getHandle();
+ msgHeader[HEADER_FIELD_MSG_TYPE] = 0;
+ msgHeader[HEADER_FIELD_MSG_VERSION] = 0;
+ msgHeader[HEADER_FIELD_HUB_HANDLE] = ANY_HUB;
+ msgHeader[HEADER_FIELD_APP_INSTANCE] = app.getHandle();
byte[] data = new byte[1];
data[0] = (byte) ((vrModeEnabled) ? 1 : 0);
diff --git a/core/java/android/net/LinkAddress.java b/core/java/android/net/LinkAddress.java
index 384ab1c8f50c..6e74f14bd138 100644
--- a/core/java/android/net/LinkAddress.java
+++ b/core/java/android/net/LinkAddress.java
@@ -103,7 +103,7 @@ public class LinkAddress implements Parcelable {
private boolean isIPv6ULA() {
if (address != null && address instanceof Inet6Address) {
byte[] bytes = address.getAddress();
- return ((bytes[0] & (byte)0xfc) == (byte)0xfc);
+ return ((bytes[0] & (byte)0xfe) == (byte)0xfc);
}
return false;
}
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index a44a9eed701b..feb8b2be3c58 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -603,6 +603,17 @@ public class UserManager {
public static final String DISALLOW_SET_USER_ICON = "no_set_user_icon";
/**
+ * Specifies if a user is not allowed to enable the oem unlock setting. The default value is
+ * <code>false</code>.
+ *
+ * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
+ * @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
+ * @see #getUserRestrictions()
+ * @hide
+ */
+ public static final String DISALLOW_OEM_UNLOCK = "no_oem_unlock";
+
+ /**
* Allows apps in the parent profile to handle web links from the managed profile.
*
* This user restriction has an effect only in a managed profile.
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 56610ed1d7ee..5c2778d483ac 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -9114,15 +9114,6 @@ public final class Settings {
public static final String ENABLE_CELLULAR_ON_BOOT = "enable_cellular_on_boot";
/**
- * Whether toggling OEM unlock is disallowed. If disallowed, it is not possible to enable or
- * disable OEM unlock.
- * <p>
- * Type: int (0: allow OEM unlock setting. 1: disallow OEM unlock)
- * @hide
- */
- public static final String OEM_UNLOCK_DISALLOWED = "oem_unlock_disallowed";
-
- /**
* The maximum allowed notification enqueue rate in Hertz.
*
* Should be a float, and includes both posts and updates.
diff --git a/core/java/android/service/notification/ZenModeConfig.java b/core/java/android/service/notification/ZenModeConfig.java
index 6911b0161704..69960b04518a 100644
--- a/core/java/android/service/notification/ZenModeConfig.java
+++ b/core/java/android/service/notification/ZenModeConfig.java
@@ -20,6 +20,8 @@ import android.app.ActivityManager;
import android.app.NotificationManager.Policy;
import android.content.ComponentName;
import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.net.Uri;
import android.os.Parcel;
@@ -118,6 +120,7 @@ public class ZenModeConfig implements Parcelable {
private static final String RULE_ATT_ZEN = "zen";
private static final String RULE_ATT_CONDITION_ID = "conditionId";
private static final String RULE_ATT_CREATION_TIME = "creationTime";
+ private static final String RULE_ATT_ENABLER = "enabler";
public boolean allowCalls = DEFAULT_ALLOW_CALLS;
public boolean allowRepeatCallers = DEFAULT_ALLOW_REPEAT_CALLERS;
@@ -502,6 +505,7 @@ public class ZenModeConfig implements Parcelable {
rt.conditionId = safeUri(parser, RULE_ATT_CONDITION_ID);
rt.component = safeComponentName(parser, RULE_ATT_COMPONENT);
rt.creationTime = safeLong(parser, RULE_ATT_CREATION_TIME, 0);
+ rt.enabler = parser.getAttributeValue(null, RULE_ATT_ENABLER);
rt.condition = readConditionXml(parser);
return rt;
}
@@ -520,6 +524,9 @@ public class ZenModeConfig implements Parcelable {
out.attribute(null, RULE_ATT_CONDITION_ID, rule.conditionId.toString());
}
out.attribute(null, RULE_ATT_CREATION_TIME, Long.toString(rule.creationTime));
+ if (rule.enabler != null) {
+ out.attribute(null, RULE_ATT_ENABLER, rule.enabler);
+ }
if (rule.condition != null) {
writeConditionXml(rule.condition, out);
}
@@ -989,6 +996,25 @@ public class ZenModeConfig implements Parcelable {
return UUID.randomUUID().toString().replace("-", "");
}
+ private static String getOwnerCaption(Context context, String owner) {
+ final PackageManager pm = context.getPackageManager();
+ try {
+ final ApplicationInfo info = pm.getApplicationInfo(owner, 0);
+ if (info != null) {
+ final CharSequence seq = info.loadLabel(pm);
+ if (seq != null) {
+ final String str = seq.toString().trim();
+ if (str.length() > 0) {
+ return str;
+ }
+ }
+ }
+ } catch (Throwable e) {
+ Slog.w(TAG, "Error loading owner caption", e);
+ }
+ return "";
+ }
+
public static String getConditionSummary(Context context, ZenModeConfig config,
int userHandle, boolean shortVersion) {
return getConditionLine(context, config, userHandle, false /*useLine1*/, shortVersion);
@@ -997,23 +1023,28 @@ public class ZenModeConfig implements Parcelable {
private static String getConditionLine(Context context, ZenModeConfig config,
int userHandle, boolean useLine1, boolean shortVersion) {
if (config == null) return "";
+ String summary = "";
if (config.manualRule != null) {
final Uri id = config.manualRule.conditionId;
- if (id == null) {
- return context.getString(com.android.internal.R.string.zen_mode_forever);
- }
- final long time = tryParseCountdownConditionId(id);
- Condition c = config.manualRule.condition;
- if (time > 0) {
- final long now = System.currentTimeMillis();
- final long span = time - now;
- c = toTimeCondition(context, time, Math.round(span / (float) MINUTES_MS),
- userHandle, shortVersion);
+ if (config.manualRule.enabler != null) {
+ summary = getOwnerCaption(context, config.manualRule.enabler);
+ } else {
+ if (id == null) {
+ summary = context.getString(com.android.internal.R.string.zen_mode_forever);
+ } else {
+ final long time = tryParseCountdownConditionId(id);
+ Condition c = config.manualRule.condition;
+ if (time > 0) {
+ final long now = System.currentTimeMillis();
+ final long span = time - now;
+ c = toTimeCondition(context, time, Math.round(span / (float) MINUTES_MS),
+ userHandle, shortVersion);
+ }
+ final String rt = c == null ? "" : useLine1 ? c.line1 : c.summary;
+ summary = TextUtils.isEmpty(rt) ? "" : rt;
+ }
}
- final String rt = c == null ? "" : useLine1 ? c.line1 : c.summary;
- return TextUtils.isEmpty(rt) ? "" : rt;
}
- String summary = "";
for (ZenRule automaticRule : config.automaticRules.values()) {
if (automaticRule.isAutomaticActive()) {
if (summary.isEmpty()) {
@@ -1023,6 +1054,7 @@ public class ZenModeConfig implements Parcelable {
.getString(R.string.zen_mode_rule_name_combination, summary,
automaticRule.name);
}
+
}
}
return summary;
@@ -1038,6 +1070,7 @@ public class ZenModeConfig implements Parcelable {
public ComponentName component; // optional
public String id; // required for automatic (unique)
public long creationTime; // required for automatic
+ public String enabler; // package name, only used for manual rules.
public ZenRule() { }
@@ -1055,6 +1088,9 @@ public class ZenModeConfig implements Parcelable {
id = source.readString();
}
creationTime = source.readLong();
+ if (source.readInt() == 1) {
+ enabler = source.readString();
+ }
}
@Override
@@ -1083,6 +1119,12 @@ public class ZenModeConfig implements Parcelable {
dest.writeInt(0);
}
dest.writeLong(creationTime);
+ if (enabler != null) {
+ dest.writeInt(1);
+ dest.writeString(enabler);
+ } else {
+ dest.writeInt(0);
+ }
}
@Override
@@ -1097,6 +1139,7 @@ public class ZenModeConfig implements Parcelable {
.append(",component=").append(component)
.append(",id=").append(id)
.append(",creationTime=").append(creationTime)
+ .append(",enabler=").append(enabler)
.append(']').toString();
}
@@ -1143,6 +1186,9 @@ public class ZenModeConfig implements Parcelable {
if (creationTime != to.creationTime) {
d.addLine(item, "creationTime", creationTime, to.creationTime);
}
+ if (enabler != to.enabler) {
+ d.addLine(item, "enabler", enabler, to.enabler);
+ }
}
@Override
@@ -1158,13 +1204,14 @@ public class ZenModeConfig implements Parcelable {
&& Objects.equals(other.condition, condition)
&& Objects.equals(other.component, component)
&& Objects.equals(other.id, id)
- && other.creationTime == creationTime;
+ && other.creationTime == creationTime
+ && Objects.equals(other.enabler, enabler);
}
@Override
public int hashCode() {
return Objects.hash(enabled, snoozing, name, zenMode, conditionId, condition,
- component, id, creationTime);
+ component, id, creationTime, enabler);
}
public boolean isAutomaticActive() {
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index e3ff54d40316..9bc0bb4b38f7 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -306,6 +306,11 @@ interface IWindowManager
boolean isRotationFrozen();
/**
+ * Screenshot the current wallpaper layer, including the whole screen.
+ */
+ Bitmap screenshotWallpaper();
+
+ /**
* Used only for assist -- request a screenshot of the current application.
*/
boolean requestAssistScreenshot(IAssistScreenshotReceiver receiver);
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index d4ac30076eaa..a64827af32c2 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -3744,7 +3744,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
/**
* Flag indicating that a drag can cross window boundaries. When
* {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)} is called
- * with this flag set, all visible applications will be able to participate
+ * with this flag set, all visible applications with targetSdkVersion >=
+ * {@link android.os.Build.VERSION_CODES#N API 24} will be able to participate
* in the drag operation and receive the dragged content.
*
* If this is the only flag set, then the drag recipient will only have access to text data
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index c42752287a42..92801a4d4575 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -1731,7 +1731,7 @@ public final class ViewRootImpl implements ViewParent,
}
boolean hwInitialized = false;
- boolean framesChanged = false;
+ boolean contentInsetsChanged = false;
boolean hadSurface = mSurface.isValid();
try {
@@ -1771,7 +1771,7 @@ public final class ViewRootImpl implements ViewParent,
final boolean overscanInsetsChanged = !mPendingOverscanInsets.equals(
mAttachInfo.mOverscanInsets);
- boolean contentInsetsChanged = !mPendingContentInsets.equals(
+ contentInsetsChanged = !mPendingContentInsets.equals(
mAttachInfo.mContentInsets);
final boolean visibleInsetsChanged = !mPendingVisibleInsets.equals(
mAttachInfo.mVisibleInsets);
@@ -1821,19 +1821,6 @@ public final class ViewRootImpl implements ViewParent,
+ mAttachInfo.mVisibleInsets);
}
- // If any of the insets changed, do a forceLayout on the view so that the
- // measure cache is cleared. We might have a pending MSG_RESIZED_REPORT
- // that is supposed to take care of it, but since pending insets are
- // already modified here, it won't detect the frame change after this.
- framesChanged = overscanInsetsChanged
- || contentInsetsChanged
- || stableInsetsChanged
- || visibleInsetsChanged
- || outsetsChanged;
- if (mAdded && mView != null && framesChanged) {
- forceLayout(mView);
- }
-
if (!hadSurface) {
if (mSurface.isValid()) {
// If we are creating a new surface, then we need to
@@ -2017,7 +2004,7 @@ public final class ViewRootImpl implements ViewParent,
boolean focusChangedDueToTouchMode = ensureTouchModeLocally(
(relayoutResult&WindowManagerGlobal.RELAYOUT_RES_IN_TOUCH_MODE) != 0);
if (focusChangedDueToTouchMode || mWidth != host.getMeasuredWidth()
- || mHeight != host.getMeasuredHeight() || framesChanged ||
+ || mHeight != host.getMeasuredHeight() || contentInsetsChanged ||
updatedConfiguration) {
int childWidthMeasureSpec = getRootMeasureSpec(mWidth, lp.width);
int childHeightMeasureSpec = getRootMeasureSpec(mHeight, lp.height);
@@ -2026,7 +2013,7 @@ public final class ViewRootImpl implements ViewParent,
+ mWidth + " measuredWidth=" + host.getMeasuredWidth()
+ " mHeight=" + mHeight
+ " measuredHeight=" + host.getMeasuredHeight()
- + " framesChanged=" + framesChanged);
+ + " coveredInsetsChanged=" + contentInsetsChanged);
// Ask host how big it wants to be
performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index eff116b7570c..0059d4df79f7 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -149,7 +149,7 @@ public class LockPatternUtils {
private DevicePolicyManager mDevicePolicyManager;
private ILockSettings mLockSettingsService;
private UserManager mUserManager;
- private final Handler mHandler = new Handler();
+ private final Handler mHandler;
/**
* Use {@link TrustManager#isTrustUsuallyManaged(int)}.
@@ -231,6 +231,9 @@ public class LockPatternUtils {
public LockPatternUtils(Context context) {
mContext = context;
mContentResolver = context.getContentResolver();
+
+ Looper looper = Looper.myLooper();
+ mHandler = looper != null ? new Handler(looper) : null;
}
private ILockSettings getLockSettings() {
@@ -1506,6 +1509,10 @@ public class LockPatternUtils {
if (callback == null) {
return null;
} else {
+ if (mHandler == null) {
+ throw new IllegalStateException("Must construct LockPatternUtils on a looper thread"
+ + " to use progress callbacks.");
+ }
return new ICheckCredentialProgressCallback.Stub() {
@Override
diff --git a/core/jni/android_hardware_location_ContextHubService.cpp b/core/jni/android_hardware_location_ContextHubService.cpp
index a56eba6c133f..46f76de87a2f 100644
--- a/core/jni/android_hardware_location_ContextHubService.cpp
+++ b/core/jni/android_hardware_location_ContextHubService.cpp
@@ -21,28 +21,34 @@
#include <inttypes.h>
#include <jni.h>
-#include <queue>
-#include <unordered_map>
+#include <mutex>
#include <string.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
+#include <unordered_map>
+#include <queue>
#include <cutils/log.h>
#include "JNIHelp.h"
#include "core_jni_helpers.h"
-static constexpr int OS_APP_ID=-1;
+static constexpr int OS_APP_ID = -1;
+static constexpr uint64_t ALL_APPS = UINT64_C(0xFFFFFFFFFFFFFFFF);
+
+static constexpr int MIN_APP_ID = 1;
+static constexpr int MAX_APP_ID = 128;
-static constexpr int MIN_APP_ID=1;
-static constexpr int MAX_APP_ID=128;
+static constexpr size_t MSG_HEADER_SIZE = 4;
+static constexpr size_t HEADER_FIELD_MSG_TYPE = 0;
+static constexpr size_t HEADER_FIELD_MSG_VERSION = 1;
+static constexpr size_t HEADER_FIELD_HUB_HANDLE = 2;
+static constexpr size_t HEADER_FIELD_APP_INSTANCE = 3;
-static constexpr size_t MSG_HEADER_SIZE=4;
-static constexpr int HEADER_FIELD_MSG_TYPE=0;
-//static constexpr int HEADER_FIELD_MSG_VERSION=1;
-static constexpr int HEADER_FIELD_HUB_HANDLE=2;
-static constexpr int HEADER_FIELD_APP_INSTANCE=3;
+static constexpr size_t HEADER_FIELD_LOAD_APP_ID_LO = MSG_HEADER_SIZE;
+static constexpr size_t HEADER_FIELD_LOAD_APP_ID_HI = MSG_HEADER_SIZE + 1;
+static constexpr size_t MSG_HEADER_SIZE_LOAD_APP = MSG_HEADER_SIZE + 2;
namespace android {
@@ -83,6 +89,7 @@ struct jniInfo_s {
jmethodID contextHubServiceMsgReceiptCallback;
jmethodID contextHubServiceAddAppInstance;
+ jmethodID contextHubServiceDeleteAppInstance;
};
struct context_hub_info_s {
@@ -93,10 +100,53 @@ struct context_hub_info_s {
};
struct app_instance_info_s {
- uint32_t hubHandle; // Id of the hub this app is on
- int instanceId; // systemwide unique instance id - assigned
+ uint64_t truncName; // Possibly truncated name for logging
+ uint32_t hubHandle; // Id of the hub this app is on
+ int instanceId; // system wide unique instance id - assigned
struct hub_app_info appInfo; // returned from the HAL
- uint64_t truncName; // Possibly truncated name - logging
+};
+
+/*
+ * TODO(ashutoshj): From original code review:
+ *
+ * So, I feel like we could possible do a better job of organizing this code,
+ * and being more C++-y. Consider something like this:
+ * class TxnManager {
+ * public:
+ * TxnManager();
+ * ~TxnManager();
+ * int add(hub_message_e identifier, void *data);
+ * int close();
+ * bool isPending() const;
+ * int fetchData(hub_message_e *identifier, void **data) const;
+ *
+ * private:
+ * bool mPending;
+ * mutable std::mutex mLock;
+ * hub_message_e mIdentifier;
+ * void *mData;
+ * };
+ *
+ * And then, for example, we'd have things like:
+ * TxnManager::TxnManager() : mPending(false), mLock(), mIdentifier(), mData(nullptr) {}
+ * int TxnManager::add(hub_message_e identifier, void *data) {
+ * std::lock_guard<std::mutex> lock(mLock);
+ * mPending = true;
+ * mData = txnData;
+ * mIdentifier = txnIdentifier;
+ * return 0;
+ * }
+ * And then calling code would look like:
+ * if (!db.txnManager.add(CONTEXT_HUB_LOAD_APP, txnInfo)) {
+ *
+ * This would make it clearer the nothing is manipulating any state within TxnManager
+ * unsafely and outside of these couple of calls.
+ */
+struct txnManager_s {
+ bool txnPending; // Is a transaction pending
+ std::mutex m; // mutex for manager
+ hub_messages_e txnIdentifier; // What are we doing
+ void *txnData; // Details
};
struct contextHubServiceDb_s {
@@ -105,12 +155,69 @@ struct contextHubServiceDb_s {
jniInfo_s jniInfo;
std::queue<int> freeIds;
std::unordered_map<int, app_instance_info_s> appInstances;
+ txnManager_s txnManager;
};
} // unnamed namespace
static contextHubServiceDb_s db;
+static bool initTxnManager() {
+ txnManager_s *mgr = &db.txnManager;
+
+ mgr->txnData = nullptr;
+ mgr->txnPending = false;
+ return true;
+}
+
+static int addTxn(hub_messages_e txnIdentifier, void *txnData) {
+ txnManager_s *mgr = &db.txnManager;
+
+ std::lock_guard<std::mutex>lock(mgr->m);
+
+ mgr->txnPending = true;
+ mgr->txnData = txnData;
+ mgr->txnIdentifier = txnIdentifier;
+
+ return 0;
+}
+
+static int closeTxn() {
+ txnManager_s *mgr = &db.txnManager;
+ std::lock_guard<std::mutex>lock(mgr->m);
+ mgr->txnPending = false;
+ free(mgr->txnData);
+ mgr->txnData = nullptr;
+
+ return 0;
+}
+
+static bool isTxnPending() {
+ txnManager_s *mgr = &db.txnManager;
+ std::lock_guard<std::mutex>lock(mgr->m);
+ return mgr->txnPending;
+}
+
+static int fetchTxnData(hub_messages_e *id, void **data) {
+ txnManager_s *mgr = &db.txnManager;
+
+ if (!id || !data) {
+ ALOGW("Null params id %p, data %p", id, data);
+ return -1;
+ }
+
+ std::lock_guard<std::mutex>lock(mgr->m);
+ if (!mgr->txnPending) {
+ ALOGW("No Transactions pending");
+ return -1;
+ }
+
+ // else
+ *id = mgr->txnIdentifier;
+ *data = mgr->txnData;
+ return 0;
+}
+
int context_hub_callback(uint32_t hubId, const struct hub_message_t *msg,
void *cookie);
@@ -152,13 +259,21 @@ static int get_hub_id_for_hub_handle(int hubHandle) {
}
}
-static int get_hub_id_for_app_instance(int id) {
+static int get_hub_handle_for_app_instance(int id) {
if (!db.appInstances.count(id)) {
ALOGD("%s: Cannot find app for app instance %d", __FUNCTION__, id);
return -1;
}
- int hubHandle = db.appInstances[id].hubHandle;
+ return db.appInstances[id].hubHandle;
+}
+
+static int get_hub_id_for_app_instance(int id) {
+ int hubHandle = get_hub_handle_for_app_instance(id);
+
+ if (hubHandle < 0) {
+ return -1;
+ }
return db.hubInfo.hubs[hubHandle].hub_id;
}
@@ -184,7 +299,7 @@ static int set_dest_app(hub_message_t *msg, int id) {
return 0;
}
-static void send_query_for_apps() {
+static void query_hub_for_apps(uint64_t appId, uint32_t hubHandle) {
hub_message_t msg;
query_apps_request_t queryMsg;
@@ -194,23 +309,31 @@ static void send_query_for_apps() {
msg.message_len = sizeof(queryMsg);
msg.message = &queryMsg;
+ ALOGD("Sending query for apps to hub %" PRIu32, hubHandle);
+ set_os_app_as_destination(&msg, hubHandle);
+ if (send_msg_to_hub(&msg, hubHandle) != 0) {
+ ALOGW("Could not query hub %" PRIu32 " for apps", hubHandle);
+ }
+}
+
+static void sendQueryForApps(uint64_t appId) {
for (int i = 0; i < db.hubInfo.numHubs; i++ ) {
- ALOGD("Sending query for apps to hub %d", i);
- set_os_app_as_destination(&msg, i);
- if (send_msg_to_hub(&msg, i) != 0) {
- ALOGW("Could not query hub %i for apps", i);
- }
+ query_hub_for_apps(appId, i);
}
}
static int return_id(int id) {
// Note : This method is not thread safe.
- // id returned is guarenteed to be in use
- db.freeIds.push(id);
- return 0;
+ // id returned is guaranteed to be in use
+ if (id >= 0) {
+ db.freeIds.push(id);
+ return 0;
+ }
+
+ return -1;
}
-static int generate_id(void) {
+static int generate_id() {
// Note : This method is not thread safe.
int retVal = -1;
@@ -222,23 +345,31 @@ static int generate_id(void) {
return retVal;
}
-int add_app_instance(const hub_app_info *appInfo, uint32_t hubHandle, JNIEnv *env) {
+
+static int add_app_instance(const hub_app_info *appInfo, uint32_t hubHandle,
+ int appInstanceHandle, JNIEnv *env) {
+
+ ALOGI("Loading App");
+
// Not checking if the apps are indeed distinct
app_instance_info_s entry;
- int appInstanceHandle = generate_id();
-
assert(appInfo);
- if (appInstanceHandle < 0) {
- ALOGE("Cannot find resources to add app instance %d",
- appInstanceHandle);
- return -1;
+ if (db.appInstances.count(appInstanceHandle) == 0) {
+ appInstanceHandle = generate_id();
+ if (appInstanceHandle < 0) {
+ ALOGE("Cannot find resources to add app instance %d",
+ appInstanceHandle);
+ return -1;
+ }
}
entry.appInfo = *appInfo;
+
entry.instanceId = appInstanceHandle;
entry.truncName = appInfo->app_name.id;
entry.hubHandle = hubHandle;
+
db.appInstances[appInstanceHandle] = entry;
// Finally - let the service know of this app instance
@@ -254,17 +385,70 @@ int add_app_instance(const hub_app_info *appInfo, uint32_t hubHandle, JNIEnv *en
return appInstanceHandle;
}
-int delete_app_instance(int id) {
+int delete_app_instance(int id, JNIEnv *env) {
if (!db.appInstances.count(id)) {
+ ALOGW("Cannot find App id : %d", id);
return -1;
}
return_id(id);
db.appInstances.erase(id);
+ if (env->CallIntMethod(db.jniInfo.jContextHubService,
+ db.jniInfo.contextHubServiceDeleteAppInstance,
+ id) != 0) {
+ ALOGW("Could not delete App id : %d", id);
+ return -1;
+ }
+
+ ALOGI("Deleted App id : %d", id);
+
+ return 0;
+}
+
+static int startLoadAppTxn(uint64_t appId, int hubHandle) {
+ app_instance_info_s *txnInfo = (app_instance_info_s *)malloc(sizeof(app_instance_info_s));
+ int instanceId = generate_id();
+
+ if (!txnInfo || instanceId < 0) {
+ return_id(instanceId);
+ free(txnInfo);
+ return -1;
+ }
+
+ txnInfo->truncName = appId;
+ txnInfo->hubHandle = hubHandle;
+ txnInfo->instanceId = instanceId;
+
+ txnInfo->appInfo.app_name.id = appId;
+ txnInfo->appInfo.num_mem_ranges = 0;
+ txnInfo->appInfo.version = -1; // Awaited
+
+ if (!addTxn(CONTEXT_HUB_LOAD_APP, txnInfo)) {
+ return_id(instanceId);
+ free(txnInfo);
+ return -1;
+ }
return 0;
}
+static int startUnloadAppTxn(uint32_t appInstanceHandle) {
+ uint32_t *txnData = (uint32_t *) malloc(sizeof(uint32_t));
+ if (!txnData) {
+ ALOGW("Cannot allocate memory to start unload transaction");
+ return -1;
+ }
+
+ *txnData = appInstanceHandle;
+
+ if (addTxn(CONTEXT_HUB_UNLOAD_APP, txnData) != 0) {
+ free(txnData);
+ ALOGW("Cannot start transaction to unload app");
+ return -1;
+ }
+
+ return 0;
+}
static void initContextHubService() {
int err = 0;
@@ -285,6 +469,7 @@ static void initContextHubService() {
db.freeIds.push(i);
}
+ initTxnManager();
if (db.hubInfo.contextHubModule) {
int retNumHubs = db.hubInfo.contextHubModule->get_hubs(db.hubInfo.contextHubModule,
&db.hubInfo.hubs);
@@ -302,6 +487,7 @@ static void initContextHubService() {
for (i = 0; i < db.hubInfo.numHubs; i++) {
db.hubInfo.cookies[i] = db.hubInfo.hubs[i].hub_id;
+ ALOGI("Subscribing to hubHandle %d with OS App name %" PRIu64, i, db.hubInfo.hubs[i].os_app_name.id);
if (db.hubInfo.contextHubModule->subscribe_messages(db.hubInfo.hubs[i].hub_id,
context_hub_callback,
&db.hubInfo.cookies[i]) == 0) {
@@ -309,7 +495,7 @@ static void initContextHubService() {
}
}
- send_query_for_apps();
+ sendQueryForApps(ALL_APPS);
} else {
ALOGW("No Context Hub Module present");
}
@@ -346,7 +532,8 @@ static int onMessageReceipt(uint32_t *header, size_t headerLen, char *msg, size_
return ret;
}
-int handle_query_apps_response(char *msg, int msgLen, uint32_t hubHandle) {
+int handle_query_apps_response(const uint8_t *msg, int msgLen,
+ uint32_t hubHandle) {
JNIEnv *env;
if ((db.jniInfo.vm)->AttachCurrentThread(&env, nullptr) != JNI_OK) {
return -1;
@@ -354,53 +541,201 @@ int handle_query_apps_response(char *msg, int msgLen, uint32_t hubHandle) {
int numApps = msgLen/sizeof(hub_app_info);
hub_app_info info;
- hub_app_info *unalignedInfoAddr = (hub_app_info*)msg;
+ const hub_app_info *unalignedInfoAddr = (const hub_app_info*)msg;
for (int i = 0; i < numApps; i++, unalignedInfoAddr++) {
memcpy(&info, unalignedInfoAddr, sizeof(info));
- add_app_instance(&info, hubHandle, env);
+ // We will only have one instance of the app
+ // TODO : Change this logic once we support multiple instances of the same app
+ int appInstance = get_app_instance_for_app_id(info.app_name.id);
+ add_app_instance(&info, hubHandle, appInstance, env);
}
return 0;
}
+static void passOnOsResponse(uint32_t hubHandle, uint32_t msgType,
+ status_response_t *rsp, int8_t *additionalData,
+ size_t additionalDataLen) {
+ JNIEnv *env;
-int handle_os_message(uint32_t msgType, uint32_t hubHandle,
- char *msg, int msgLen) {
- int retVal;
+ if ((db.jniInfo.vm)->AttachCurrentThread(&env, nullptr) != JNI_OK) {
+ ALOGW("Cannot latch to JNI env, dropping OS response %" PRIu32, msgType);
+ return;
+ }
- //ALOGD("Rcd OS message from hubHandle %" PRIu32 " type %" PRIu32 " length %d",
- // hubHandle, msgType, msgLen);
+ uint32_t header[MSG_HEADER_SIZE];
+ memset(header, 0, sizeof(header));
- switch(msgType) {
- case CONTEXT_HUB_APPS_ENABLE:
- retVal = 0;
- break;
+ if (!additionalData) {
+ additionalDataLen = 0; // clamp
+ }
+ int msgLen = 1 + additionalDataLen;
- case CONTEXT_HUB_APPS_DISABLE:
- retVal = 0;
- break;
+ int8_t *msg = new int8_t[msgLen];
- case CONTEXT_HUB_LOAD_APP:
- retVal = 0;
- break;
+ if (!msg) {
+ ALOGW("Unexpected : Ran out of memory, cannot send response");
+ return;
+ }
+
+ header[HEADER_FIELD_MSG_TYPE] = msgType;
+ header[HEADER_FIELD_MSG_VERSION] = 0;
+ header[HEADER_FIELD_HUB_HANDLE] = hubHandle;
+ header[HEADER_FIELD_APP_INSTANCE] = OS_APP_ID;
+
+ msg[0] = rsp->result;
+
+ if (additionalData) {
+ memcpy(&msg[1], additionalData, additionalDataLen);
+ }
+
+ jbyteArray jmsg = env->NewByteArray(msgLen);
+ jintArray jheader = env->NewIntArray(sizeof(header));
+
+ env->SetByteArrayRegion(jmsg, 0, msgLen, (jbyte *)msg);
+ env->SetIntArrayRegion(jheader, 0, sizeof(header), (jint *)header);
+
+ ALOGI("Passing msg type %" PRIu32 " from app %" PRIu32 " from hub %" PRIu32,
+ header[HEADER_FIELD_MSG_TYPE], header[HEADER_FIELD_APP_INSTANCE],
+ header[HEADER_FIELD_HUB_HANDLE]);
+
+ env->CallIntMethod(db.jniInfo.jContextHubService,
+ db.jniInfo.contextHubServiceMsgReceiptCallback,
+ jheader, jmsg);
+
+ delete[] msg;
+}
+
+void closeUnloadTxn(bool success) {
+ void *txnData = nullptr;
+ hub_messages_e txnId;
+
+ if (success && fetchTxnData(&txnId, &txnData) == 0 &&
+ txnId == CONTEXT_HUB_UNLOAD_APP) {
+ db.appInstances.erase(*(uint32_t *)txnData);
+ } else {
+ ALOGW("Could not unload the app successfully ! success %d, txnData %p", success, txnData);
+ }
+
+ closeTxn();
+}
+
+void closeLoadTxn(bool success, int *appInstanceHandle) {
+ void *txnData;
+ hub_messages_e txnId;
+
+ if (success && fetchTxnData(&txnId, &txnData) == 0 &&
+ txnId == CONTEXT_HUB_LOAD_APP) {
+ app_instance_info_s *info = (app_instance_info_s *)txnData;
+ *appInstanceHandle = info->instanceId;
+
+ JNIEnv *env;
+ if ((db.jniInfo.vm)->AttachCurrentThread(&env, nullptr) == JNI_OK) {
+ add_app_instance(&info->appInfo, info->hubHandle, info->instanceId, env);
+ } else {
+ ALOGW("Could not attach to JVM !");
+ }
+ sendQueryForApps(info->appInfo.app_name.id);
+ } else {
+ ALOGW("Could not load the app successfully ! Unexpected failure");
+ }
+
+ closeTxn();
+}
+
+static bool isValidOsStatus(const uint8_t *msg, size_t msgLen,
+ status_response_t *rsp) {
+ // Workaround a bug in some HALs
+ if (msgLen == 1) {
+ rsp->result = msg[0];
+ return true;
+ }
+
+ if (!msg || msgLen != sizeof(*rsp)) {
+ ALOGW("Received invalid response %p of size %zu", msg, msgLen);
+ return false;
+ }
+
+ memcpy(rsp, msg, sizeof(*rsp));
+
+ // No sanity checks on return values
+ return true;
+}
+
+static void invalidateNanoApps(uint32_t hubHandle) {
+ JNIEnv *env;
+
+ if ((db.jniInfo.vm)->AttachCurrentThread(&env, nullptr) != JNI_OK) {
+ ALOGW("Could not attach to JVM !");
+ }
+
+ auto end = db.appInstances.end();
+ for (auto current = db.appInstances.begin(); current != end; ) {
+ app_instance_info_s info = current->second;
+ current++;
+ if (info.hubHandle == hubHandle) {
+ delete_app_instance(info.instanceId, env);
+ }
+ }
+}
- case CONTEXT_HUB_UNLOAD_APP:
- retVal = 0;
- break;
+static int handle_os_message(uint32_t msgType, uint32_t hubHandle,
+ const uint8_t *msg, int msgLen) {
+ int retVal = -1;
- case CONTEXT_HUB_QUERY_APPS:
- retVal = handle_query_apps_response(msg, msgLen, hubHandle);
- break;
+ ALOGD("Rcd OS message from hubHandle %" PRIu32 " type %" PRIu32 " length %d",
+ hubHandle, msgType, msgLen);
- case CONTEXT_HUB_QUERY_MEMORY:
- retVal = 0;
- break;
+ struct status_response_t rsp;
- default:
- retVal = -1;
- break;
+ switch(msgType) {
+ case CONTEXT_HUB_APPS_ENABLE:
+ case CONTEXT_HUB_APPS_DISABLE:
+ case CONTEXT_HUB_LOAD_APP:
+ case CONTEXT_HUB_UNLOAD_APP:
+ if (isValidOsStatus(msg, msgLen, &rsp)) {
+ if (msgType == CONTEXT_HUB_LOAD_APP) {
+ int appInstanceHandle;
+ closeLoadTxn(rsp.result == 0, &appInstanceHandle);
+ passOnOsResponse(hubHandle, msgType, &rsp, (int8_t *)(&appInstanceHandle),
+ sizeof(appInstanceHandle));
+ } else if (msgType == CONTEXT_HUB_UNLOAD_APP) {
+ closeUnloadTxn(rsp.result == 0);
+ passOnOsResponse(hubHandle, msgType, &rsp, nullptr, 0);
+ } else {
+ passOnOsResponse(hubHandle, msgType, &rsp, nullptr, 0);
+ }
+ retVal = 0;
+ }
+ break;
+
+ case CONTEXT_HUB_QUERY_APPS:
+ rsp.result = 0;
+ retVal = handle_query_apps_response(msg, msgLen, hubHandle);
+ passOnOsResponse(hubHandle, msgType, &rsp, nullptr, 0);
+ break;
+
+ case CONTEXT_HUB_QUERY_MEMORY:
+ // Deferring this use
+ retVal = 0;
+ break;
+
+ case CONTEXT_HUB_OS_REBOOT:
+ if (isValidOsStatus(msg, msgLen, &rsp)) {
+ rsp.result = 0;
+ ALOGW("Context Hub handle %d restarted", hubHandle);
+ passOnOsResponse(hubHandle, msgType, &rsp, nullptr, 0);
+ invalidateNanoApps(hubHandle);
+ query_hub_for_apps(ALL_APPS, hubHandle);
+ retVal = 0;
+ }
+ break;
+
+ default:
+ retVal = -1;
+ break;
}
return retVal;
@@ -420,10 +755,12 @@ static bool sanity_check_cookie(void *cookie, uint32_t hub_id) {
}
}
+
int context_hub_callback(uint32_t hubId,
const struct hub_message_t *msg,
void *cookie) {
if (!msg) {
+ ALOGW("NULL message");
return -1;
}
if (!sanity_check_cookie(cookie, hubId)) {
@@ -433,11 +770,12 @@ int context_hub_callback(uint32_t hubId,
return -1;
}
+
uint32_t messageType = msg->message_type;
uint32_t hubHandle = *(uint32_t*) cookie;
if (messageType < CONTEXT_HUB_TYPE_PRIVATE_MSG_BASE) {
- handle_os_message(messageType, hubHandle, (char*) msg->message, msg->message_len);
+ handle_os_message(messageType, hubHandle, (uint8_t*) msg->message, msg->message_len);
} else {
int appHandle = get_app_instance_for_app_id(msg->app_name.id);
if (appHandle < 0) {
@@ -528,7 +866,9 @@ static int init_jni(JNIEnv *env, jobject instance) {
env->GetMethodID(db.jniInfo.contextHubServiceClass,
"addAppInstance", "(IIJI)I");
-
+ db.jniInfo.contextHubServiceDeleteAppInstance =
+ env->GetMethodID(db.jniInfo.contextHubServiceClass,
+ "deleteAppInstance", "(I)I");
return 0;
}
@@ -538,8 +878,6 @@ static jobject constructJContextHubInfo(JNIEnv *env, const struct context_hub_t
jintArray jintBuf;
jobjectArray jmemBuf;
- int dummyConnectedSensors[] = {1, 2, 3, 4, 5};
-
jobject jHub = env->NewObject(db.jniInfo.contextHubInfoClass,
db.jniInfo.contextHubInfoCtor);
env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetId, hub->hub_id);
@@ -569,11 +907,21 @@ static jobject constructJContextHubInfo(JNIEnv *env, const struct context_hub_t
hub->max_supported_msg_len);
- // TODO : jintBuf = env->NewIntArray(hub->num_connected_sensors);
- // TODO : env->SetIntArrayRegion(jintBuf, 0, hub->num_connected_sensors,
- // hub->connected_sensors);
- jintBuf = env->NewIntArray(array_length(dummyConnectedSensors));
- env->SetIntArrayRegion(jintBuf, 0, hub->num_connected_sensors, dummyConnectedSensors);
+ jintBuf = env->NewIntArray(hub->num_connected_sensors);
+ int *connectedSensors = new int[hub->num_connected_sensors];
+
+ if (!connectedSensors) {
+ ALOGW("Cannot allocate memory! Unexpected");
+ assert(false);
+ } else {
+ for (unsigned int i = 0; i < hub->num_connected_sensors; i++) {
+ connectedSensors[i] = hub->connected_sensors[i].sensor_id;
+ }
+ }
+
+ env->SetIntArrayRegion(jintBuf, 0, hub->num_connected_sensors,
+ connectedSensors);
+
env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetSupportedSensors, jintBuf);
env->DeleteLocalRef(jintBuf);
@@ -584,6 +932,7 @@ static jobject constructJContextHubInfo(JNIEnv *env, const struct context_hub_t
env->DeleteLocalRef(jmemBuf);
+ delete[] connectedSensors;
return jHub;
}
@@ -622,33 +971,96 @@ static jint nativeSendMessage(JNIEnv *env, jobject instance, jintArray header_,
jbyte *data = env->GetByteArrayElements(data_, 0);
int dataBufferLength = env->GetArrayLength(data_);
+ if (numHeaderElements < MSG_HEADER_SIZE) {
+ ALOGW("Malformed header len");
+ return -1;
+ }
+
+ uint32_t appInstanceHandle = header[HEADER_FIELD_APP_INSTANCE];
+ uint32_t msgType = header[HEADER_FIELD_MSG_TYPE];
+ int hubHandle = -1;
+ int hubId;
+ uint64_t appId;
+
+ if (msgType == CONTEXT_HUB_UNLOAD_APP) {
+ hubHandle = get_hub_handle_for_app_instance(appInstanceHandle);
+ } else if (msgType == CONTEXT_HUB_LOAD_APP) {
+ if (numHeaderElements < MSG_HEADER_SIZE_LOAD_APP) {
+ return -1;
+ }
+ uint64_t appIdLo = header[HEADER_FIELD_LOAD_APP_ID_LO];
+ uint64_t appIdHi = header[HEADER_FIELD_LOAD_APP_ID_HI];
+ appId = appIdHi << 32 | appIdLo;
+
+ hubHandle = header[HEADER_FIELD_HUB_HANDLE];
+ } else {
+ hubHandle = header[HEADER_FIELD_HUB_HANDLE];
+ }
+
+ if (hubHandle < 0) {
+ ALOGD("Invalid hub Handle %d", hubHandle);
+ return -1;
+ }
+
+ if (msgType == CONTEXT_HUB_LOAD_APP ||
+ msgType == CONTEXT_HUB_UNLOAD_APP) {
+
+ if (isTxnPending()) {
+ ALOGW("Cannot load or unload app while a transaction is pending !");
+ return -1;
+ }
- if (numHeaderElements >= MSG_HEADER_SIZE) {
- bool setAddressSuccess;
- int hubId;
- hub_message_t msg;
+ if (msgType == CONTEXT_HUB_LOAD_APP) {
+ if (startLoadAppTxn(appId, hubHandle) != 0) {
+ return -1;
+ }
+ } else if (msgType == CONTEXT_HUB_UNLOAD_APP) {
+ if (startUnloadAppTxn(appInstanceHandle) != 0) {
+ return -1;
+ }
+ }
+ }
+
+ bool setAddressSuccess = false;
+ hub_message_t msg;
+
+ msg.message_type = msgType;
+
+ if (msgType == CONTEXT_HUB_UNLOAD_APP) {
+ msg.message_len = sizeof(db.appInstances[appInstanceHandle].appInfo.app_name);
+ msg.message = &db.appInstances[appInstanceHandle].appInfo.app_name;
+ setAddressSuccess = (set_os_app_as_destination(&msg, hubHandle) == 0);
+ hubId = get_hub_id_for_hub_handle(hubHandle);
+ } else {
+ msg.message_len = dataBufferLength;
+ msg.message = data;
if (header[HEADER_FIELD_APP_INSTANCE] == OS_APP_ID) {
- setAddressSuccess = (set_os_app_as_destination(&msg, header[HEADER_FIELD_HUB_HANDLE]) == 0);
- hubId = get_hub_id_for_hub_handle(header[HEADER_FIELD_HUB_HANDLE]);
+ setAddressSuccess = (set_os_app_as_destination(&msg, hubHandle) == 0);
+ hubId = get_hub_id_for_hub_handle(hubHandle);
} else {
setAddressSuccess = (set_dest_app(&msg, header[HEADER_FIELD_APP_INSTANCE]) == 0);
hubId = get_hub_id_for_app_instance(header[HEADER_FIELD_APP_INSTANCE]);
}
+ }
- if (setAddressSuccess && hubId >= 0) {
- msg.message_type = header[HEADER_FIELD_MSG_TYPE];
- msg.message_len = dataBufferLength;
- msg.message = data;
- retVal = db.hubInfo.contextHubModule->send_message(hubId, &msg);
- } else {
- ALOGD("Could not find app instance %d on hubHandle %d, setAddress %d",
- header[HEADER_FIELD_APP_INSTANCE],
- header[HEADER_FIELD_HUB_HANDLE],
- (int)setAddressSuccess);
- }
+ if (setAddressSuccess && hubId >= 0) {
+ ALOGD("Asking HAL to remove app");
+ retVal = db.hubInfo.contextHubModule->send_message(hubId, &msg);
} else {
- ALOGD("Malformed header len");
+ ALOGD("Could not find app instance %d on hubHandle %d, setAddress %d",
+ header[HEADER_FIELD_APP_INSTANCE],
+ header[HEADER_FIELD_HUB_HANDLE],
+ (int)setAddressSuccess);
+ }
+
+ if (retVal != 0) {
+ ALOGD("Send Message failure - %d", retVal);
+ if (msgType == CONTEXT_HUB_LOAD_APP) {
+ closeLoadTxn(false, nullptr);
+ } else if (msgType == CONTEXT_HUB_UNLOAD_APP) {
+ closeUnloadTxn(false);
+ }
}
env->ReleaseIntArrayElements(header_, header, 0);
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 7d195370c6db..c7b605d2504a 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2527,4 +2527,12 @@
<!-- Package name for the device provisioning package. -->
<string name="config_deviceProvisioningPackage"></string>
+
+ <!-- Colon separated list of package names that should be granted DND access -->
+ <string name="config_defaultDndAccessPackages" translatable="false">com.android.camera2</string>
+
+ <!-- User restrictions set when the first user is created.
+ Note: Also update appropriate overlay files. -->
+ <string-array translatable="false" name="config_defaultFirstUserRestrictions">
+ </string-array>
</resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index ff5f7d9b86f5..91cfd91d0357 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2639,6 +2639,9 @@
<!-- Package name for the device provisioning package -->
<java-symbol type="string" name="config_deviceProvisioningPackage" />
+ <!-- Colon separated list of package names that should be granted DND access -->
+ <java-symbol type="string" name="config_defaultDndAccessPackages" />
+
<!-- Used for MimeIconUtils. -->
<java-symbol type="drawable" name="ic_doc_apk" />
<java-symbol type="drawable" name="ic_doc_audio" />
@@ -2668,4 +2671,7 @@
<java-symbol type="integer" name="config_defaultNightDisplayAutoMode" />
<java-symbol type="integer" name="config_defaultNightDisplayCustomStartTime" />
<java-symbol type="integer" name="config_defaultNightDisplayCustomEndTime" />
+
+ <!-- Default first user restrictions -->
+ <java-symbol type="array" name="config_defaultFirstUserRestrictions" />
</resources>
diff --git a/docs/html/_redirects.yaml b/docs/html/_redirects.yaml
index 11e06f110bec..48aca2860edd 100644
--- a/docs/html/_redirects.yaml
+++ b/docs/html/_redirects.yaml
@@ -801,8 +801,8 @@ redirects:
to: http://android-developers.blogspot.com/2016/03/first-preview-of-android-n-developer.html
- from: /reference/org/apache/http/...
to: /about/versions/marshmallow/android-6.0-changes.html#behavior-apache-http-client
-- from: /shareables/
- to: https://commondatastorage.googleapis.com/androiddevelopers/shareables/
+- from: /shareables/...
+ to: https://commondatastorage.googleapis.com/androiddevelopers/shareables/...
- from: /downloads/
to: https://commondatastorage.googleapis.com/androiddevelopers/
- from: /training/performance/battery/network/action-any-traffic.html
@@ -1193,3 +1193,5 @@ redirects:
to: http://tools.android.com/tech-docs/new-build-system/gradle-experimental/experimental-to-stable-gradle
- from: /r/studio-ui/sdk-manager.html
to: https://developer.android.com/studio/intro/update.html#sdk-manager
+- from: /r/studio-ui/newjclass.html
+ to: /studio/write/index.html
diff --git a/docs/html/distribute/stories/apps.jd b/docs/html/distribute/stories/apps.jd
index 9c2e8e9680a4..76e9f5ac368b 100644
--- a/docs/html/distribute/stories/apps.jd
+++ b/docs/html/distribute/stories/apps.jd
@@ -29,5 +29,5 @@ page.metaDescription=How app developers are making use of localization, tablet f
data-sortOrder="-timestamp"
data-cardSizes="6x6"
data-items-per-page="15"
- data-initial-results="3"></div>
+ data-initial-results="6"></div>
</div></section> \ No newline at end of file
diff --git a/docs/html/distribute/stories/apps/aftenposten.jd b/docs/html/distribute/stories/apps/aftenposten.jd
new file mode 100644
index 000000000000..f1f388e2b6bd
--- /dev/null
+++ b/docs/html/distribute/stories/apps/aftenposten.jd
@@ -0,0 +1,80 @@
+page.title=Aftenposten Improves Retention by Allowing Readers to Customize Notifications
+page.metaDescription=Aftenposten upgraded their app and improved user retention.
+page.tags="developerstory", "apps", "googleplay"
+page.image=images/cards/distribute/stories/aftenposten.png
+page.timestamp=1468270114
+
+@jd:body
+
+<div class="figure" style="width:113px">
+ <img src="{@docRoot}images/distribute/stories/aftenposten-icon.png" height=
+ "106">
+</div>
+
+<h3>
+ Background
+</h3>
+
+<p>
+ Aftenposten is one of the largest newspapers in Norway. Their <a class=
+ "external-link" href=
+ "https://play.google.com/store/apps/details?id=no.cita&amp;e=-EnableAppDetailsPageRedesign">
+ news app</a> was released on Android in 2013.
+</p>
+
+<p>
+ Aftenposten found that sending too many notifications, with no user control
+ over the default <em>on</em> setting or differentiation between general and
+ breaking news, caused many people to uninstall their app. They changed the
+ user controls for notifications and used the native Android share button in
+ the app, <strong>which reduced user uninstalls</strong>.
+</p>
+
+<h3>
+ What they did
+</h3>
+
+<p>
+ Aftenposten created a new onboarding flow that explained what notifications
+ were available, allowing readers to manage their preferences and customize up
+ to three topics. They also changed their custom share icon for the native
+ Android app.
+</p>
+
+<h3>
+ Results
+</h3>
+
+<p>
+ The results showed that with the new notifications management onboarding
+ screen, <strong>uninstalls decreased by 9.2% over 60 days</strong>. And with
+ the option to customize notifications, 51% of readers decided to keep two out
+ of three topics turned on. This led to a <strong>28% decrease over 60 days in
+ the number of users muting notifications completely</strong>. It also
+ provided insight into users’ content preferences, with <em>Sport</em> being
+ the least-favored notification.
+</p>
+
+<p>
+ Aftenposten also increased share interactions by 17% just by replacing their
+ custom share icon with the native Android share icon.
+</p>
+
+<p>
+ Aftenposten commented that: <em>Many of our users who see the onboarding
+ screen interact with it by turning off at least one notification topic. This
+ means that users are accepting push from one or more topics, instead of
+ turning it off completely. Moreover, readers are sharing more articles since
+ we added the standard share Android icon.</em>
+</p>
+
+<h3>
+ Get started
+</h3>
+
+<p>
+ Find out more about best practices for <a href=
+ "{@docRoot}design/patterns/notifications.html">Notifications</a> and <a href=
+ "{@docRoot}training/building-content-sharing.html">Building Apps with Content
+ Sharing</a>.
+</p>
diff --git a/docs/html/distribute/stories/apps/el-mundo.jd b/docs/html/distribute/stories/apps/el-mundo.jd
new file mode 100644
index 000000000000..2ee813d55d11
--- /dev/null
+++ b/docs/html/distribute/stories/apps/el-mundo.jd
@@ -0,0 +1,73 @@
+page.title=El Mundo Improves User Ratings and Engagement with Material Design
+page.metaDescription=El Mundo uses Material Design principles to enhance their app's user experience.
+page.tags="developerstory", "apps", "googleplay"
+page.image=images/cards/distribute/stories/el-mundo.png
+page.timestamp=1468270112
+
+@jd:body
+
+<div class="figure" style="width:113px">
+ <img src="{@docRoot}images/distribute/stories/el-mundo-icon.png" height=
+ "113">
+</div>
+
+<h3>
+ Background
+</h3>
+
+<p>
+ <a class="external-link" href=
+ "https://play.google.com/store/apps/details?id=com.gi.elmundo.main">El
+ Mundo</a>, one of Spain’s largest newspapers, integrated material design
+ principles into their app, which helped increase their Google Play Store
+ rating and improve user engagement.
+</p>
+
+<h3>
+ What they did
+</h3>
+
+<p>
+ El Mundo decided to completely redesign their app to provide a higher quality
+ user experience, making it easier for their readers to engage with news
+ content. By implementing material design guidelines, they created a
+ consistent look and feel throughout their app.
+</p>
+
+<p>
+ After analyzing user comments, El Mundo discovered that readers considered
+ their app to be complicated and out-of-date. Therefore, they decided to
+ simplify the app’s functionality by removing features that were redundant.
+ They also removed sections of their app that were less relevant to their
+ readers, such as weather updates and movie trailers. Finally, they applied a
+ brand new internal development framework that they now use consistently
+ across all of their apps.
+</p>
+
+<h3>
+ Results
+</h3>
+
+<p>
+ Following the re-launch of their material design app, El Mundo saw a
+ <strong>45% increase in the weekly install rate</strong>. Readers now spend
+ more time in the app, with the average time spent in-app increasing from one
+ to three minutes.
+</p>
+
+<p>
+ Additionally, this redesign resulted in more readers providing positive
+ feedback around the new experience, increasing the app rating in the Google
+ Play store by 25.8%, from 3.1 to 3.9.
+</p>
+
+<h3>
+ Get started
+</h3>
+
+<p>
+ Learn how to integrate <a class="external-link" href=
+ "https://material.google.com">Material Design</a> guidelines and follow
+ <a class="external-link" href="https://design.google.com">design
+ principles</a> for your app.
+</p>
diff --git a/docs/html/distribute/stories/apps/segundamano.jd b/docs/html/distribute/stories/apps/segundamano.jd
new file mode 100644
index 000000000000..4cbf817c6d43
--- /dev/null
+++ b/docs/html/distribute/stories/apps/segundamano.jd
@@ -0,0 +1,63 @@
+page.title=Segundamano Develops Android-First as Its Fastest Channel for Growth
+page.metaDescription=Segundamano developed Android app to increase potential for growth.
+page.tags="developerstory", "apps", "googleplay"
+page.image=images/cards/distribute/stories/segundamano.png
+page.timestamp=1468270110
+
+@jd:body
+
+<div class="figure" style="width:113px">
+ <img src="{@docRoot}images/distribute/stories/segundamano-icon.png" height=
+ "113">
+</div>
+
+<h3>
+ Background
+</h3>
+
+<p>
+ <a class="external-link" href=
+ "https://play.google.com/store/apps/details?id=mx.segundamano.android">Segundamano</a>
+ is a leading shopping application in Mexico for second-hand products. They
+ started by placing classified ads in newspapers, progressed to desktop, and
+ over the past year have seen significant growth in mobile, which now accounts
+ for 70% of their business. They have also seen <strong>270% year-over-year
+ growth on the Android platform alone</strong>.
+</p>
+
+<h3>
+ What they did
+</h3>
+
+<p>
+ Segundamano shifted focus to mobile with their Android app because of the
+ high potential for growth. From July 2015 to January 2016, they saw an
+ increase of 55% in the number of classified ads on Android, higher than any
+ other platform. To leverage this momentum, Segundamano implemented two new
+ features on Android: premium offers and push notifications. Segundamano also
+ decided to implement material design in order to improve the in-app
+ experience and streamline the sales process for users.
+</p>
+
+<h3>
+ Results
+</h3>
+
+<p>
+ Following Segundamano’s enhancements to the user experience, they've seen an
+ increase in their star rating, a 4.7% lift in monthly active users, and a 7%
+ increase in sales of premium listings. Additionally, year-to-date, their
+ <strong>installs are over seven times higher on Android than on other
+ platforms</strong>.
+</p>
+
+<h3>
+ Get started
+</h3>
+
+<p>
+ Learn more about simplifying your in-app experience with <a href=
+ "{@docRoot}guide/topics/ui/notifiers/notifications.html">Notifications</a>
+ and the <a href="{@docRoot}design/material/index.html">material design
+ guidelines</a>.
+</p> \ No newline at end of file
diff --git a/docs/html/distribute/stories/apps/tapps.jd b/docs/html/distribute/stories/apps/tapps.jd
new file mode 100644
index 000000000000..129213946630
--- /dev/null
+++ b/docs/html/distribute/stories/apps/tapps.jd
@@ -0,0 +1,366 @@
+page.title=Tapps Games Increases Installs by More Than 20% with Store Listing Experiments
+page.metaDescription=Tapps Games increased their use of store listing experiments in the Developer Console, with impressive results.
+page.tags="developerstory", "apps", "googleplay"
+page.image=images/cards/distribute/stories/tapps.png
+page.timestamp=1468270108
+
+@jd:body
+
+<style type="text/css">
+ span.positive{
+ color:green;
+ font-size: 125%;
+ font-weight:bold;">
+ }
+ span.negative{
+ color:red;
+ font-size: 125%;
+ font-weight:bold;">
+ }
+</style>
+
+<div class="figure" style="width:215px">
+ <img src="{@docRoot}images/distribute/stories/tapps-logo.png" height="65">
+</div>
+
+<h3>
+ Background
+</h3>
+
+<p>
+ <a class="external-link" href=
+ "https://play.google.com/store/apps/dev?id=6615809648420562690">Tapps</a> is
+ a mobile game publisher in São Paulo, Brazil. With a mission of <em>creating
+ fun for everyone</em>, Tapps has a portfolio of over 200 titles on the Google
+ Play Store, with roughly 70% of their installs coming from Android. Store
+ listing experiments have provided invaluable metrics to help their growing
+ team understand what makes the most effective product listings.
+</p>
+
+<h3>
+ What they did
+</h3>
+
+<p>
+ Tapps has increased their use of store listing experiments in the Developer
+ Console. They recently expanded their marketing team to allocate greater time
+ and designated resources to the Developer Console tools. <strong>"We can’t
+ stress enough how much value the store listing experiments have brought us
+ over the past months. Right now, our marketing team has a substantial time
+ allocated to these tests every week,"</strong> said Felipe Watanabe, head of
+ marketing at Tapps. With icons and screenshots, Tapps tested variations in
+ color, character positioning, and the overall amount of graphic detail. In
+ the description tests, they found that shorter messages with clear calls to
+ action and appropriate language localizations were most successful.
+</p>
+
+<h3>
+ Results
+</h3>
+
+<p>
+ By frequently conducting store listing experiments, Tapps gained valuable
+ insights that they have applied across their greater portfolio of games.
+ Results showed that shortening messaging, using contrasting colors,
+ reordering screenshots, and simplifying graphics often led to variant results
+ representing an average increase in performance between 5% and 50%. After
+ making changes based on the test results, Tapps saw <strong>install rates
+ increase beyond 20-30%</strong>.
+</p>
+
+<h4>
+ Screen tests
+</h4>
+
+<p>
+ The following table compares the install rates for three apps based on
+ changes to each app's screenshot.
+</p>
+
+<p class="table-caption">
+ <strong>Table 1</strong>. Screen test results
+</p>
+
+<table>
+ <tr>
+ <th>
+ Original
+ </th>
+ <th>
+ Variant
+ </th>
+ <th>
+ Variant results
+ </th>
+ </tr>
+
+ <tr>
+ <td>
+ <img src="{@docRoot}images/distribute/stories/tapps-screen-orig-3.png"
+ width="240">
+ </td>
+ <td>
+ <img src="{@docRoot}images/distribute/stories/tapps-screen-var-3.png"
+ width="240">
+ </td>
+ <td>
+ <span class="positive">+25%</span>
+ </td>
+ </tr>
+
+ <tr>
+ <td>
+ <img src="{@docRoot}images/distribute/stories/tapps-screen-orig-1.png"
+ width="240">
+ </td>
+ <td>
+ <img src="{@docRoot}images/distribute/stories/tapps-screen-var-1.png"
+ width="240">
+ </td>
+ <td>
+ <span class="positive">+17.1%</span>
+ </td>
+ </tr>
+
+ <tr>
+ <td>
+ <img src="{@docRoot}images/distribute/stories/tapps-screen-orig-2.png"
+ width="240">
+ </td>
+ <td>
+ <img src="{@docRoot}images/distribute/stories/tapps-screen-var-2.png"
+ width="240">
+ </td>
+ <td>
+ <span class="positive">+7.4%</span>
+ </td>
+ </tr>
+
+</table>
+
+<h4>
+ Icon tests
+</h4>
+
+<p>
+ The following tables compare install rates for three apps based on changes
+ to each app's icon.
+</p>
+
+<p class="table-caption">
+ <strong>Table 2</strong>. Icon 1 test results
+</p>
+
+<table>
+ <tr>
+ <th>
+ Original
+ </th>
+ <th>
+ Variant 1
+ </th>
+ <th>
+ Variant 2
+ </th>
+ </tr>
+
+ <tr>
+ <td>
+ <img src="{@docRoot}images/distribute/stories/tapps-icon-orig-1.png">
+ </td>
+ <td>
+ <img src="{@docRoot}images/distribute/stories/tapps-icon-var-1.png">
+ </td>
+ <td>
+ <img src="{@docRoot}images/distribute/stories/tapps-icon-var-1-2.png">
+ </td>
+ </tr>
+
+ <tr>
+ <td>
+ ---
+ </td>
+ <td>
+ <span class="negative">-29.6%</span>
+ </td>
+ <td>
+ <span class="positive">+20.8%</span>
+ </td>
+ </tr>
+</table>
+
+<p class="table-caption">
+ <strong>Table 3</strong>. Icon 2 test results
+</p>
+
+<table>
+ <tr>
+ <th>
+ Original
+ </th>
+ <th>
+ Variant 1
+ </th>
+ <th>
+ Variant 2
+ </th>
+ </tr>
+
+ <tr>
+ <td>
+ <img src="{@docRoot}images/distribute/stories/tapps-icon-orig-2.png">
+ </td>
+ <td>
+ <img src="{@docRoot}images/distribute/stories/tapps-icon-var-2.png">
+ </td>
+ <td>
+ <img src="{@docRoot}images/distribute/stories/tapps-icon-var-2-2.png">
+ </td>
+ </tr>
+
+ <tr>
+ <td>
+ ---
+ </td>
+ <td>
+ <span class="positive">+5.1%</span>
+ </td>
+ <td>
+ <span class="positive">+19.7%</span>
+ </td>
+ </tr>
+</table>
+
+<p class="table-caption">
+ <strong>Table 4</strong>. Icon 3 test results
+</p>
+
+<table>
+ <tr>
+ <th>
+ Original
+ </th>
+ <th>
+ Variant 1
+ </th>
+ <th>
+ Variant 2
+ </th>
+ </tr>
+
+ <tr>
+ <td>
+ <img src="{@docRoot}images/distribute/stories/tapps-icon-orig-3.png">
+ </td>
+ <td>
+ <img src="{@docRoot}images/distribute/stories/tapps-icon-var-3.png">
+ </td>
+ <td>
+ <img src="{@docRoot}images/distribute/stories/tapps-icon-var-3-2.png">
+ </td>
+ </tr>
+
+ <tr>
+ <td>
+ ---
+ </td>
+ <td>
+ <span class="negative">-17.7%</span>
+ </td>
+ <td>
+ <span class="positive">+50.7%</span>
+ </td>
+ </tr>
+</table>
+
+<h4>
+ Description tests
+</h4>
+
+<p>
+ The following table compares install rates for three apps based on changes to
+ each app's description text.
+</p>
+
+<p class="table-caption">
+ <strong>Table 5</strong>. Description test results
+</p>
+
+<table>
+ <tr>
+ <th>
+ Game
+ </th>
+ <th>
+ Original
+ </th>
+ <th>
+ Variant
+ </th>
+ <th>
+ Variant results
+ </th>
+ </tr>
+
+ <tr>
+ <td>
+ <img src="{@docRoot}images/distribute/stories/tapps-logic-pic.png">
+ <strong>Logic Pic</strong>
+ </td>
+ <td>
+ <em>"Use logic to solve fun puzzles and discover hidden pictures! Logic
+ Pic is free!"</em>
+ </td>
+ <td>
+ <strong><em>"Discover all the hidden pictures in this challenging classic
+ japanese puzzle!"</em></strong>
+ </td>
+ <td>
+ <span class="positive">+10.7%</span>
+ </td>
+ </tr>
+
+ <tr>
+ <td>
+ <img src="{@docRoot}images/distribute/stories/tapps-candy-hills.png"
+ width="96"> <strong>Candy Hills</strong>
+ </td>
+ <td>
+ <em>"What will your candy park look like? Build it now in Candy
+ Hills!"</em>
+ </td>
+ <td>
+ <strong><em>"Build your own sweet candy park in Candy
+ Hills!"</em></strong>
+ </td>
+ <td>
+ <span class="positive">+8.2%</span>
+ </td>
+ </tr>
+
+ <tr>
+ <td>
+ <img src="{@docRoot}images/distribute/stories/tapps-villains-corp.png"
+ width="96"> <strong>Villains Corp.</strong>
+ </td>
+ <td>
+ <em>"Be a real villain and CONQUER THE WORLD!"</em>
+ </td>
+ <td>
+ <strong><em>"Mwahahaha! Be a real villain and CONQUER THE
+ WORLD!"</em></strong>
+ </td>
+ <td>
+ <span class="positive">+6.8%</span>
+ </td>
+ </tr>
+</table>
+
+<h3>
+ Get started
+</h3>
+
+<p>
+ Find out more about <a href=
+ "{@docRoot}distribute/users/experiments.html">store listing experiments</a>.
+</p>
diff --git a/docs/html/distribute/stories/apps/upbeat-games.jd b/docs/html/distribute/stories/apps/upbeat-games.jd
new file mode 100644
index 000000000000..02222d39e686
--- /dev/null
+++ b/docs/html/distribute/stories/apps/upbeat-games.jd
@@ -0,0 +1,69 @@
+page.title=Witch Puzzle Achieves 98% of International Installs on Android
+page.metaDescription=Witch Puzzle localized their app into 12 languages.
+page.tags="developerstory", "apps", "googleplay"
+page.image=images/cards/distribute/stories/witch-puzzle.png
+page.timestamp=1468270106
+
+@jd:body
+
+
+<div class="figure">
+ <img src="{@docRoot}images/distribute/stories/witch-puzzle-icon.png"
+ width="113">
+</div>
+
+<h3>
+ Background
+</h3>
+
+<p>
+ Located in São Paulo, Brazil, <a class="external-link" href=
+ "https://play.google.com/store/apps/dev?id=8995071809141037139">Upbeat
+ Games</a> is an indie game developer with a mission to build fun and easy
+ games that anyone can play. As a small team, the Upbeat crew reacted quickly
+ to their game’s growing installs in Asian countries, and is now seeing strong
+ international growth with their game <a class="external-link" href=
+ "https://play.google.com/store/apps/details?id=com.upbeatgames.witchpuzzle">Witch
+ Puzzle</a>.
+</p>
+
+<h3>
+ What they did
+</h3>
+
+<p>
+ After noticing that Witch Puzzle was gaining traction throughout Asia, Upbeat
+ localized their game into 12 languages, prioritizing countries with an
+ existing user base and high gross national income (GNI). This led to a direct
+ increase in installs.
+</p>
+
+<div class="figure">
+ <img src="{@docRoot}images/distribute/stories/japanese-witch-puzzle.png"
+ width="214">
+ <p class="img-caption">
+ Japanese version of Witch Puzzle
+ </p>
+</div>
+
+<h3>
+ Results
+</h3>
+
+<p>
+ “In the last three months, 98% of our international installs for Witch Puzzle
+ came from Android,” said Vinicius Sormani Heimbeck, Upbeat’s founder. Upbeat
+ applied these learnings across their portfolio of games. Now, <strong>75% of
+ their portfolio’s revenue is driven by Android</strong>.
+</p>
+
+<h3>
+ Get started
+</h3>
+
+<p>
+ Use the <a href=
+ "{@docRoot}distribute/tools/localization-checklist.html">Localization
+ Checklist</a> to learn more about tailoring your app for different markets to
+ drive installs and revenue, and to create a better overall user experience.
+</p>
diff --git a/docs/html/images/cards/distribute/stories/aftenposten.png b/docs/html/images/cards/distribute/stories/aftenposten.png
new file mode 100644
index 000000000000..60cb85104f8c
--- /dev/null
+++ b/docs/html/images/cards/distribute/stories/aftenposten.png
Binary files differ
diff --git a/docs/html/images/cards/distribute/stories/el-mundo.png b/docs/html/images/cards/distribute/stories/el-mundo.png
new file mode 100644
index 000000000000..23db783d47dd
--- /dev/null
+++ b/docs/html/images/cards/distribute/stories/el-mundo.png
Binary files differ
diff --git a/docs/html/images/cards/distribute/stories/segundamano.png b/docs/html/images/cards/distribute/stories/segundamano.png
new file mode 100644
index 000000000000..60e873c0c8cb
--- /dev/null
+++ b/docs/html/images/cards/distribute/stories/segundamano.png
Binary files differ
diff --git a/docs/html/images/cards/distribute/stories/tapps.png b/docs/html/images/cards/distribute/stories/tapps.png
new file mode 100644
index 000000000000..e01e3adf596d
--- /dev/null
+++ b/docs/html/images/cards/distribute/stories/tapps.png
Binary files differ
diff --git a/docs/html/images/cards/distribute/stories/witch-puzzle.png b/docs/html/images/cards/distribute/stories/witch-puzzle.png
new file mode 100644
index 000000000000..c336f1bf16ef
--- /dev/null
+++ b/docs/html/images/cards/distribute/stories/witch-puzzle.png
Binary files differ
diff --git a/docs/html/images/distribute/stories/aftenposten-icon.png b/docs/html/images/distribute/stories/aftenposten-icon.png
new file mode 100644
index 000000000000..60cb85104f8c
--- /dev/null
+++ b/docs/html/images/distribute/stories/aftenposten-icon.png
Binary files differ
diff --git a/docs/html/images/distribute/stories/el-mundo-icon.png b/docs/html/images/distribute/stories/el-mundo-icon.png
new file mode 100644
index 000000000000..23db783d47dd
--- /dev/null
+++ b/docs/html/images/distribute/stories/el-mundo-icon.png
Binary files differ
diff --git a/docs/html/images/distribute/stories/japanese-witch-puzzle.png b/docs/html/images/distribute/stories/japanese-witch-puzzle.png
new file mode 100644
index 000000000000..6a7ef13dd9f9
--- /dev/null
+++ b/docs/html/images/distribute/stories/japanese-witch-puzzle.png
Binary files differ
diff --git a/docs/html/images/distribute/stories/segundamano-icon.png b/docs/html/images/distribute/stories/segundamano-icon.png
new file mode 100644
index 000000000000..60e873c0c8cb
--- /dev/null
+++ b/docs/html/images/distribute/stories/segundamano-icon.png
Binary files differ
diff --git a/docs/html/images/distribute/stories/tapps-candy-hills.png b/docs/html/images/distribute/stories/tapps-candy-hills.png
new file mode 100644
index 000000000000..14dcb9447ba6
--- /dev/null
+++ b/docs/html/images/distribute/stories/tapps-candy-hills.png
Binary files differ
diff --git a/docs/html/images/distribute/stories/tapps-icon-orig-1.png b/docs/html/images/distribute/stories/tapps-icon-orig-1.png
new file mode 100644
index 000000000000..44af423f3795
--- /dev/null
+++ b/docs/html/images/distribute/stories/tapps-icon-orig-1.png
Binary files differ
diff --git a/docs/html/images/distribute/stories/tapps-icon-orig-2.png b/docs/html/images/distribute/stories/tapps-icon-orig-2.png
new file mode 100644
index 000000000000..1b362557b2b0
--- /dev/null
+++ b/docs/html/images/distribute/stories/tapps-icon-orig-2.png
Binary files differ
diff --git a/docs/html/images/distribute/stories/tapps-icon-orig-3.png b/docs/html/images/distribute/stories/tapps-icon-orig-3.png
new file mode 100644
index 000000000000..2f393f8ba965
--- /dev/null
+++ b/docs/html/images/distribute/stories/tapps-icon-orig-3.png
Binary files differ
diff --git a/docs/html/images/distribute/stories/tapps-icon-var-1-2.png b/docs/html/images/distribute/stories/tapps-icon-var-1-2.png
new file mode 100644
index 000000000000..fecab6e06f90
--- /dev/null
+++ b/docs/html/images/distribute/stories/tapps-icon-var-1-2.png
Binary files differ
diff --git a/docs/html/images/distribute/stories/tapps-icon-var-1.png b/docs/html/images/distribute/stories/tapps-icon-var-1.png
new file mode 100644
index 000000000000..77bd02a17f63
--- /dev/null
+++ b/docs/html/images/distribute/stories/tapps-icon-var-1.png
Binary files differ
diff --git a/docs/html/images/distribute/stories/tapps-icon-var-2-2.png b/docs/html/images/distribute/stories/tapps-icon-var-2-2.png
new file mode 100644
index 000000000000..84166c43c9f1
--- /dev/null
+++ b/docs/html/images/distribute/stories/tapps-icon-var-2-2.png
Binary files differ
diff --git a/docs/html/images/distribute/stories/tapps-icon-var-2.png b/docs/html/images/distribute/stories/tapps-icon-var-2.png
new file mode 100644
index 000000000000..939c2fdf1b34
--- /dev/null
+++ b/docs/html/images/distribute/stories/tapps-icon-var-2.png
Binary files differ
diff --git a/docs/html/images/distribute/stories/tapps-icon-var-3-2.png b/docs/html/images/distribute/stories/tapps-icon-var-3-2.png
new file mode 100644
index 000000000000..4aa782d0b9f9
--- /dev/null
+++ b/docs/html/images/distribute/stories/tapps-icon-var-3-2.png
Binary files differ
diff --git a/docs/html/images/distribute/stories/tapps-icon-var-3.png b/docs/html/images/distribute/stories/tapps-icon-var-3.png
new file mode 100644
index 000000000000..1e44fdf7cfbc
--- /dev/null
+++ b/docs/html/images/distribute/stories/tapps-icon-var-3.png
Binary files differ
diff --git a/docs/html/images/distribute/stories/tapps-logic-pic.png b/docs/html/images/distribute/stories/tapps-logic-pic.png
new file mode 100644
index 000000000000..5029f79ca610
--- /dev/null
+++ b/docs/html/images/distribute/stories/tapps-logic-pic.png
Binary files differ
diff --git a/docs/html/images/distribute/stories/tapps-logo.png b/docs/html/images/distribute/stories/tapps-logo.png
new file mode 100644
index 000000000000..e01e3adf596d
--- /dev/null
+++ b/docs/html/images/distribute/stories/tapps-logo.png
Binary files differ
diff --git a/docs/html/images/distribute/stories/tapps-screen-orig-1.png b/docs/html/images/distribute/stories/tapps-screen-orig-1.png
new file mode 100644
index 000000000000..d54e75c8dd80
--- /dev/null
+++ b/docs/html/images/distribute/stories/tapps-screen-orig-1.png
Binary files differ
diff --git a/docs/html/images/distribute/stories/tapps-screen-orig-2.png b/docs/html/images/distribute/stories/tapps-screen-orig-2.png
new file mode 100644
index 000000000000..a2d18e3cd0da
--- /dev/null
+++ b/docs/html/images/distribute/stories/tapps-screen-orig-2.png
Binary files differ
diff --git a/docs/html/images/distribute/stories/tapps-screen-orig-3.png b/docs/html/images/distribute/stories/tapps-screen-orig-3.png
new file mode 100644
index 000000000000..e01fe20fb6b2
--- /dev/null
+++ b/docs/html/images/distribute/stories/tapps-screen-orig-3.png
Binary files differ
diff --git a/docs/html/images/distribute/stories/tapps-screen-var-1.png b/docs/html/images/distribute/stories/tapps-screen-var-1.png
new file mode 100644
index 000000000000..b93035093d3f
--- /dev/null
+++ b/docs/html/images/distribute/stories/tapps-screen-var-1.png
Binary files differ
diff --git a/docs/html/images/distribute/stories/tapps-screen-var-2.png b/docs/html/images/distribute/stories/tapps-screen-var-2.png
new file mode 100644
index 000000000000..9ccb8a647e44
--- /dev/null
+++ b/docs/html/images/distribute/stories/tapps-screen-var-2.png
Binary files differ
diff --git a/docs/html/images/distribute/stories/tapps-screen-var-3.png b/docs/html/images/distribute/stories/tapps-screen-var-3.png
new file mode 100644
index 000000000000..8eb58e1cb6d1
--- /dev/null
+++ b/docs/html/images/distribute/stories/tapps-screen-var-3.png
Binary files differ
diff --git a/docs/html/images/distribute/stories/tapps-villains-corp.png b/docs/html/images/distribute/stories/tapps-villains-corp.png
new file mode 100644
index 000000000000..6e037dad4f23
--- /dev/null
+++ b/docs/html/images/distribute/stories/tapps-villains-corp.png
Binary files differ
diff --git a/docs/html/images/distribute/stories/witch-puzzle-icon.png b/docs/html/images/distribute/stories/witch-puzzle-icon.png
new file mode 100644
index 000000000000..c336f1bf16ef
--- /dev/null
+++ b/docs/html/images/distribute/stories/witch-puzzle-icon.png
Binary files differ
diff --git a/docs/html/topic/performance/index.jd b/docs/html/topic/performance/index.jd
index 08c610f291dc..e08db15baa08 100644
--- a/docs/html/topic/performance/index.jd
+++ b/docs/html/topic/performance/index.jd
@@ -1,6 +1,6 @@
page.title=Performance
page.article=true
-page.metaDescription=Android Performance does nice things. Details to come.
+page.metaDescription=Improve your app's performance by learning how to optimize power consumption, launch times, and other important areas of performance.
meta.tags="performance"
page.tags="performance"
diff --git a/docs/html/topic/performance/launch-time.jd b/docs/html/topic/performance/launch-time.jd
index c9ce1d56185f..84d5fab12a6b 100644
--- a/docs/html/topic/performance/launch-time.jd
+++ b/docs/html/topic/performance/launch-time.jd
@@ -112,7 +112,7 @@ other.
</p>
<br/>
- <img src="{@docRoot}performance/images/cold-launch.png">
+ <img src="{@docRoot}topic/performance/images/cold-launch.png">
<p class="img-caption">
<strong>Figure 1.</strong> A visual representation of the important parts of
a cold application launch.
@@ -262,7 +262,7 @@ the {@code Displayed} time.
</p>
<br/>
- <img src="{@docRoot}performance/images/displayed-logcat.png">
+ <img src="{@docRoot}topic/performance/images/displayed-logcat.png">
<p class="img-caption">
<strong>Figure 2.</strong> Disabling filters, and
finding the {@code Displayed} value in logcat.
diff --git a/libs/hwui/PropertyValuesAnimatorSet.h b/libs/hwui/PropertyValuesAnimatorSet.h
index 49021bc82825..f9274e173536 100644
--- a/libs/hwui/PropertyValuesAnimatorSet.h
+++ b/libs/hwui/PropertyValuesAnimatorSet.h
@@ -60,7 +60,7 @@ public:
virtual uint32_t dirtyMask();
bool isInfinite() { return mIsInfinite; }
void setVectorDrawable(VectorDrawableRoot* vd) { mVectorDrawable = vd; }
- VectorDrawableRoot* getVectorDrawable() const { return mVectorDrawable; }
+ VectorDrawableRoot* getVectorDrawable() const { return mVectorDrawable.get(); }
AnimationListener* getOneShotListener() { return mOneShotListener.get(); }
void clearOneShotListener() { mOneShotListener = nullptr; }
uint32_t getRequestId() const { return mRequestId; }
@@ -78,7 +78,7 @@ private:
std::vector< std::unique_ptr<PropertyAnimator> > mAnimators;
float mLastFraction = 0.0f;
bool mInitialized = false;
- VectorDrawableRoot* mVectorDrawable = nullptr;
+ sp<VectorDrawableRoot> mVectorDrawable;
bool mIsInfinite = false;
// This request id gets incremented (on UI thread only) when a new request to modfiy the
// lifecycle of an animation happens, namely when start/end/reset/reverse is called.
diff --git a/location/java/android/location/GnssMeasurementsEvent.java b/location/java/android/location/GnssMeasurementsEvent.java
index 315169472a7c..7db04663c83b 100644
--- a/location/java/android/location/GnssMeasurementsEvent.java
+++ b/location/java/android/location/GnssMeasurementsEvent.java
@@ -98,13 +98,13 @@ public final class GnssMeasurementsEvent implements Parcelable {
throw new InvalidParameterException("Parameter 'clock' must not be null.");
}
if (measurements == null || measurements.length == 0) {
- throw new InvalidParameterException(
- "Parameter 'measurements' must not be null or empty.");
+ mReadOnlyMeasurements = Collections.emptyList();
+ } else {
+ Collection<GnssMeasurement> measurementCollection = Arrays.asList(measurements);
+ mReadOnlyMeasurements = Collections.unmodifiableCollection(measurementCollection);
}
mClock = clock;
- Collection<GnssMeasurement> measurementCollection = Arrays.asList(measurements);
- mReadOnlyMeasurements = Collections.unmodifiableCollection(measurementCollection);
}
/**
diff --git a/media/java/android/media/AudioFormat.java b/media/java/android/media/AudioFormat.java
index 7d5939c9720a..81cc93da2e6f 100644
--- a/media/java/android/media/AudioFormat.java
+++ b/media/java/android/media/AudioFormat.java
@@ -264,7 +264,6 @@ public final class AudioFormat implements Parcelable {
*/
public static final int ENCODING_IEC61937 = 13;
/** Audio data format: DOLBY TRUEHD compressed
- * @hide
**/
public static final int ENCODING_DOLBY_TRUEHD = 14;
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index 8d4a1510715a..31c7a3249542 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -3498,7 +3498,7 @@ public class MediaPlayer extends PlayerBase
* @param extra an extra code, specific to the info. Typically
* implementation dependent.
* @return True if the method handled the info, false if it didn't.
- * Returning false, or not having an OnErrorListener at all, will
+ * Returning false, or not having an OnInfoListener at all, will
* cause the info to be discarded.
*/
boolean onInfo(MediaPlayer mp, int what, int extra);
diff --git a/media/java/android/media/PlayerBase.java b/media/java/android/media/PlayerBase.java
index 0f7dc9a819c7..b262d97cfb8e 100644
--- a/media/java/android/media/PlayerBase.java
+++ b/media/java/android/media/PlayerBase.java
@@ -181,10 +181,15 @@ public abstract class PlayerBase {
* @return
*/
boolean isRestricted_sync() {
+ // check app ops
+ if (mHasAppOpsPlayAudio) {
+ return false;
+ }
+ // check bypass flag
if ((mAttributes.getAllFlags() & AudioAttributes.FLAG_BYPASS_INTERRUPTION_POLICY) != 0) {
return false;
}
- return !mHasAppOpsPlayAudio;
+ return true;
}
// Abstract methods a subclass needs to implement
diff --git a/media/java/android/media/SoundPool.java b/media/java/android/media/SoundPool.java
index 5ede1d5f7c91..9fafda48d652 100644
--- a/media/java/android/media/SoundPool.java
+++ b/media/java/android/media/SoundPool.java
@@ -505,27 +505,31 @@ public class SoundPool {
}
private boolean isRestricted() {
- IAudioService service = getService();
- boolean cameraSoundForced = false;
-
- try {
- cameraSoundForced = service.isCameraSoundForced();
- } catch (RemoteException e) {
- Log.e(TAG, "Cannot access AudioService in isRestricted()");
- }
-
- if (cameraSoundForced &&
- ((mAttributes.getAllFlags() & AudioAttributes.FLAG_AUDIBILITY_ENFORCED) != 0)
-// FIXME: should also check usage when set properly by camera app
-// && (mAttributes.getUsage() == AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
- ) {
+ // check app ops
+ if (mHasAppOpsPlayAudio) {
return false;
}
-
+ // check bypass flag
if ((mAttributes.getAllFlags() & AudioAttributes.FLAG_BYPASS_INTERRUPTION_POLICY) != 0) {
return false;
}
- return !mHasAppOpsPlayAudio;
+ // check force audibility flag and camera restriction
+ if ((mAttributes.getAllFlags() & AudioAttributes.FLAG_AUDIBILITY_ENFORCED) != 0) {
+// FIXME: should also check usage when set properly by camera app
+// && (mAttributes.getUsage() == AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
+ boolean cameraSoundForced = false;
+ try {
+ cameraSoundForced = getService().isCameraSoundForced();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Cannot access AudioService in isRestricted()");
+ } catch (NullPointerException e) {
+ Log.e(TAG, "Null AudioService in isRestricted()");
+ }
+ if (cameraSoundForced) {
+ return false;
+ }
+ }
+ return true;
}
private void updateAppOpsPlayAudio() {
diff --git a/media/java/android/media/soundtrigger/SoundTriggerDetector.java b/media/java/android/media/soundtrigger/SoundTriggerDetector.java
index df0961bd17d4..d5296ae42031 100644
--- a/media/java/android/media/soundtrigger/SoundTriggerDetector.java
+++ b/media/java/android/media/soundtrigger/SoundTriggerDetector.java
@@ -15,6 +15,7 @@
*/
package android.media.soundtrigger;
+import static android.hardware.soundtrigger.SoundTrigger.STATUS_OK;
import android.annotation.IntDef;
import android.annotation.NonNull;
@@ -243,27 +244,29 @@ public final class SoundTriggerDetector {
boolean allowMultipleTriggers =
(recognitionFlags & RECOGNITION_FLAG_ALLOW_MULTIPLE_TRIGGERS) != 0;
+ int status = STATUS_OK;
try {
- mSoundTriggerService.startRecognition(new ParcelUuid(mSoundModelId),
+ status = mSoundTriggerService.startRecognition(new ParcelUuid(mSoundModelId),
mRecognitionCallback, new RecognitionConfig(captureTriggerAudio,
allowMultipleTriggers, null, null));
} catch (RemoteException e) {
return false;
}
- return true;
+ return status == STATUS_OK;
}
/**
* Stops recognition for the associated model.
*/
public boolean stopRecognition() {
+ int status = STATUS_OK;
try {
- mSoundTriggerService.stopRecognition(new ParcelUuid(mSoundModelId),
+ status = mSoundTriggerService.stopRecognition(new ParcelUuid(mSoundModelId),
mRecognitionCallback);
} catch (RemoteException e) {
return false;
}
- return true;
+ return status == STATUS_OK;
}
/**
diff --git a/media/jni/android_media_MediaDataSource.cpp b/media/jni/android_media_MediaDataSource.cpp
index d07942b5fd89..2ab7e39fad17 100644
--- a/media/jni/android_media_MediaDataSource.cpp
+++ b/media/jni/android_media_MediaDataSource.cpp
@@ -26,6 +26,7 @@
#include "JNIHelp.h"
#include <binder/MemoryDealer.h>
+#include <drm/drm_framework_common.h>
#include <media/stagefright/foundation/ADebug.h>
#include <nativehelper/ScopedLocalRef.h>
@@ -159,4 +160,8 @@ String8 JMediaDataSource::toString() {
return String8::format("JMediaDataSource(pid %d, uid %d)", getpid(), getuid());
}
+sp<DecryptHandle> JMediaDataSource::DrmInitialization(const char * /* mime */) {
+ return NULL;
+}
+
} // namespace android
diff --git a/media/jni/android_media_MediaDataSource.h b/media/jni/android_media_MediaDataSource.h
index 378baf433fed..39405d2db579 100644
--- a/media/jni/android_media_MediaDataSource.h
+++ b/media/jni/android_media_MediaDataSource.h
@@ -47,6 +47,7 @@ public:
virtual void close();
virtual uint32_t getFlags();
virtual String8 toString();
+ virtual sp<DecryptHandle> DrmInitialization(const char *mime);
private:
// Protect all member variables with mLock because this object will be
diff --git a/packages/DocumentsUI/src/com/android/documentsui/SaveFragment.java b/packages/DocumentsUI/src/com/android/documentsui/SaveFragment.java
index d830c61f30e7..a37590d2e0a6 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/SaveFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/SaveFragment.java
@@ -22,6 +22,7 @@ import android.app.FragmentTransaction;
import android.content.Context;
import android.os.Bundle;
import android.text.Editable;
+import android.text.TextUtils;
import android.text.TextWatcher;
import android.view.KeyEvent;
import android.view.LayoutInflater;
@@ -91,6 +92,14 @@ public class SaveFragment extends Fragment {
return false;
}
+ // Returning false in this method will bubble the event up to
+ // {@link BaseActivity#onKeyDown}. In order to prevent backspace popping
+ // documents once the textView is empty, we are going to trap it here.
+ if (keyCode == KeyEvent.KEYCODE_DEL
+ && TextUtils.isEmpty(mDisplayName.getText())) {
+ return true;
+ }
+
if (keyCode == KeyEvent.KEYCODE_ENTER && mSave.isEnabled()) {
performSave();
return true;
diff --git a/packages/PrintSpooler/res/drawable/print_button.xml b/packages/PrintSpooler/res/drawable/print_button.xml
index b59afba80293..01141032e66f 100644
--- a/packages/PrintSpooler/res/drawable/print_button.xml
+++ b/packages/PrintSpooler/res/drawable/print_button.xml
@@ -16,7 +16,7 @@
-->
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
- android:color="@color/print_button_tint_color">
+ android:color="?android:attr/colorControlHighlight">
<item
android:drawable="@drawable/print_button_background">
</item>
diff --git a/packages/PrintSpooler/res/values/colors.xml b/packages/PrintSpooler/res/values/colors.xml
index 47e616ef40c7..9464c678e59c 100644
--- a/packages/PrintSpooler/res/values/colors.xml
+++ b/packages/PrintSpooler/res/values/colors.xml
@@ -16,8 +16,6 @@
<resources>
- <color name="print_button_tint_color">#EEFF41</color>
-
<color name="print_preview_scrim_color">#99000000</color>
<color name="print_preview_background_color">#F2F1F2</color>
diff --git a/packages/SettingsProvider/res/values/defaults.xml b/packages/SettingsProvider/res/values/defaults.xml
index 108814e66348..978ca9466ff1 100644
--- a/packages/SettingsProvider/res/values/defaults.xml
+++ b/packages/SettingsProvider/res/values/defaults.xml
@@ -216,7 +216,4 @@
<!-- Default setting for ability to add users from the lock screen -->
<bool name="def_add_users_from_lockscreen">false</bool>
-
- <!-- Default setting for disallow oem unlock. -->
- <bool name="def_oem_unlock_disallow">false</bool>
</resources>
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 950c7d33b672..1928f92f5855 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -799,7 +799,8 @@ public class SettingsProvider extends ContentProvider {
// If this is a setting that is currently restricted for this user, do not allow
// unrestricting changes.
- if (isGlobalOrSecureSettingRestrictedForUser(name, callingUserId, value)) {
+ if (isGlobalOrSecureSettingRestrictedForUser(name, callingUserId, value,
+ Binder.getCallingUid())) {
return false;
}
@@ -930,7 +931,8 @@ public class SettingsProvider extends ContentProvider {
// If this is a setting that is currently restricted for this user, do not allow
// unrestricting changes.
- if (isGlobalOrSecureSettingRestrictedForUser(name, callingUserId, value)) {
+ if (isGlobalOrSecureSettingRestrictedForUser(name, callingUserId, value,
+ Binder.getCallingUid())) {
return false;
}
@@ -1153,7 +1155,7 @@ public class SettingsProvider extends ContentProvider {
* @return true if the change is prohibited, false if the change is allowed.
*/
private boolean isGlobalOrSecureSettingRestrictedForUser(String setting, int userId,
- String value) {
+ String value, int callingUid) {
String restriction;
switch (setting) {
case Settings.Secure.LOCATION_MODE:
@@ -1191,6 +1193,15 @@ public class SettingsProvider extends ContentProvider {
restriction = UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS;
break;
+ case Settings.Secure.ALWAYS_ON_VPN_APP:
+ case Settings.Secure.ALWAYS_ON_VPN_LOCKDOWN:
+ // Whitelist system uid (ConnectivityService) and root uid to change always-on vpn
+ if (callingUid == Process.SYSTEM_UID || callingUid == Process.ROOT_UID) {
+ return false;
+ }
+ restriction = UserManager.DISALLOW_CONFIG_VPN;
+ break;
+
default:
if (setting != null && setting.startsWith(Settings.Global.DATA_ROAMING)) {
if ("0".equals(value)) return false;
@@ -2074,7 +2085,7 @@ public class SettingsProvider extends ContentProvider {
}
private final class UpgradeController {
- private static final int SETTINGS_VERSION = 128;
+ private static final int SETTINGS_VERSION = 129;
private final int mUserId;
@@ -2330,17 +2341,41 @@ public class SettingsProvider extends ContentProvider {
}
if (currentVersion == 127) {
- // Version 127: Disable OEM unlock setting by default on some devices.
- final SettingsState globalSettings = getGlobalSettingsLocked();
- String defaultOemUnlockDisabled = (getContext().getResources()
- .getBoolean(R.bool.def_oem_unlock_disallow) ? "1" : "0");
- globalSettings.insertSettingLocked(
- Settings.Global.OEM_UNLOCK_DISALLOWED,
- defaultOemUnlockDisabled,
- SettingsState.SYSTEM_PACKAGE_NAME);
+ // version 127 is no longer used.
currentVersion = 128;
}
+ if (currentVersion == 128) {
+ // Version 128: Allow OEMs to grant DND access to default apps. Note that
+ // the new apps are appended to the list of already approved apps.
+ final SettingsState systemSecureSettings =
+ getSecureSettingsLocked(userId);
+
+ final Setting policyAccess = systemSecureSettings.getSettingLocked(
+ Settings.Secure.ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES);
+ String defaultPolicyAccess = getContext().getResources().getString(
+ com.android.internal.R.string.config_defaultDndAccessPackages);
+ if (!TextUtils.isEmpty(defaultPolicyAccess)) {
+ if (policyAccess.isNull()) {
+ systemSecureSettings.insertSettingLocked(
+ Settings.Secure.ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES,
+ defaultPolicyAccess,
+ SettingsState.SYSTEM_PACKAGE_NAME);
+ } else {
+ StringBuilder currentSetting =
+ new StringBuilder(policyAccess.getValue());
+ currentSetting.append(":");
+ currentSetting.append(defaultPolicyAccess);
+ systemSecureSettings.updateSettingLocked(
+ Settings.Secure.ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES,
+ currentSetting.toString(),
+ SettingsState.SYSTEM_PACKAGE_NAME);
+ }
+ }
+
+ currentVersion = 129;
+ }
+
// vXXX: Add new settings above this point.
// Return the current version.
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 3b8b909118f1..6673d6e8255f 100644
--- a/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
+++ b/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
@@ -111,7 +111,7 @@
android:layout_alignParentTop="true"
android:paddingStart="16dp"
android:paddingEnd="16dp"
- android:paddingTop="2dp"
+ android:paddingTop="6dp"
android:visibility="gone"
android:textAppearance="@style/TextAppearance.StatusBar.Expanded.EmergencyCallsOnly"
android:text="@*android:string/emergency_calls_only"
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index e1cbbc5c9c54..ae4f3cf37ce7 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -375,6 +375,8 @@
<!-- The font size of the date in QS -->
<dimen name="qs_date_collapsed_size">14sp</dimen>
+ <!-- Amount the date/time move when emergency calls only is present -->
+ <dimen name="qs_date_time_translation">8dp</dimen>
<!-- Battery level text padding end when in expanded QS and on Keyguard -->
<dimen name="battery_level_padding_end">2dp</dimen>
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
index af2a2869bc30..9eceeacc3968 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
@@ -47,7 +47,7 @@ public class AssistManager {
private static final long TIMEOUT_SERVICE = 2500;
private static final long TIMEOUT_ACTIVITY = 1000;
- private final Context mContext;
+ protected final Context mContext;
private final WindowManager mWindowManager;
private final AssistDisclosure mAssistDisclosure;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonDispatcher.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonDispatcher.java
index b53a99907146..63f726b545db 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonDispatcher.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonDispatcher.java
@@ -49,6 +49,13 @@ public class ButtonDispatcher {
mViews.clear();
}
+ void addView(View view, boolean landscape) {
+ addView(view);
+ if (view instanceof ButtonInterface) {
+ ((ButtonInterface) view).setLandscape(landscape);
+ }
+ }
+
void addView(View view) {
mViews.add(view);
view.setOnClickListener(mClickListener);
@@ -178,5 +185,7 @@ public class ButtonDispatcher {
void setImageDrawable(@Nullable Drawable drawable);
void abortCurrentGesture();
+
+ void setLandscape(boolean landscape);
}
}
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 dd46b085e005..06c8b685ff63 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
@@ -28,7 +28,6 @@ import android.widget.LinearLayout;
import android.widget.Space;
import com.android.systemui.R;
-import com.android.systemui.SystemUIFactory;
import com.android.systemui.statusbar.policy.KeyButtonView;
import com.android.systemui.tuner.TunerService;
@@ -71,6 +70,8 @@ public class NavigationBarInflaterView extends FrameLayout implements TunerServi
private View mLastRot0;
private View mLastRot90;
+ private boolean mAlternativeOrder;
+
public NavigationBarInflaterView(Context context, AttributeSet attrs) {
super(context, attrs);
mDensity = context.getResources().getConfiguration().densityDpi;
@@ -114,6 +115,7 @@ public class NavigationBarInflaterView extends FrameLayout implements TunerServi
false);
mRot90.setId(R.id.rot90);
addView(mRot90);
+ updateAlternativeOrder();
if (getParent() instanceof NavigationBarView) {
((NavigationBarView) getParent()).updateRotatedViews();
}
@@ -152,6 +154,26 @@ public class NavigationBarInflaterView extends FrameLayout implements TunerServi
}
}
+ public void setAlternativeOrder(boolean alternativeOrder) {
+ if (alternativeOrder != mAlternativeOrder) {
+ mAlternativeOrder = alternativeOrder;
+ updateAlternativeOrder();
+ }
+ }
+
+ private void updateAlternativeOrder() {
+ updateAlternativeOrder(mRot0.findViewById(R.id.ends_group));
+ updateAlternativeOrder(mRot0.findViewById(R.id.center_group));
+ updateAlternativeOrder(mRot90.findViewById(R.id.ends_group));
+ updateAlternativeOrder(mRot90.findViewById(R.id.center_group));
+ }
+
+ private void updateAlternativeOrder(View v) {
+ if (v instanceof ReverseLinearLayout) {
+ ((ReverseLinearLayout) v).setAlternativeOrder(mAlternativeOrder);
+ }
+ }
+
private void initiallyFill(ButtonDispatcher buttonDispatcher) {
addAll(buttonDispatcher, (ViewGroup) mRot0.findViewById(R.id.ends_group));
addAll(buttonDispatcher, (ViewGroup) mRot0.findViewById(R.id.center_group));
@@ -258,7 +280,7 @@ public class NavigationBarInflaterView extends FrameLayout implements TunerServi
params.width = (int) (params.width * size);
}
parent.addView(v);
- addToDispatchers(v);
+ addToDispatchers(v, landscape);
View lastView = landscape ? mLastRot90 : mLastRot0;
if (lastView != null) {
v.setAccessibilityTraversalAfter(lastView.getId());
@@ -305,16 +327,16 @@ public class NavigationBarInflaterView extends FrameLayout implements TunerServi
return buttonSpec.substring(0, buttonSpec.indexOf(SIZE_MOD_START));
}
- private void addToDispatchers(View v) {
+ private void addToDispatchers(View v, boolean landscape) {
if (mButtonDispatchers != null) {
final int indexOfKey = mButtonDispatchers.indexOfKey(v.getId());
if (indexOfKey >= 0) {
- mButtonDispatchers.valueAt(indexOfKey).addView(v);
+ mButtonDispatchers.valueAt(indexOfKey).addView(v, landscape);
} 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));
+ addToDispatchers(viewGroup.getChildAt(i), landscape);
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index 53fe6ce3efa9..23aeae8c5b33 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -99,6 +99,8 @@ public class NavigationBarView extends LinearLayout {
private final SparseArray<ButtonDispatcher> mButtonDisatchers = new SparseArray<>();
private Configuration mConfiguration;
+ private NavigationBarInflaterView mNavigationInflaterView;
+
private class NavTransitionListener implements TransitionListener {
private boolean mBackTransitioning;
private boolean mHomeAppearing;
@@ -472,9 +474,10 @@ public class NavigationBarView extends LinearLayout {
@Override
public void onFinishInflate() {
+ mNavigationInflaterView = (NavigationBarInflaterView) findViewById(
+ R.id.navigation_inflater);
updateRotatedViews();
- ((NavigationBarInflaterView) findViewById(R.id.navigation_inflater)).setButtonDispatchers(
- mButtonDisatchers);
+ mNavigationInflaterView.setButtonDispatchers(mButtonDisatchers);
getImeSwitchButton().setOnClickListener(mImeSwitcherClickListener);
@@ -530,6 +533,7 @@ public class NavigationBarView extends LinearLayout {
}
mCurrentView = mRotatedViews[rot];
mCurrentView.setVisibility(View.VISIBLE);
+ mNavigationInflaterView.setAlternativeOrder(rot == Surface.ROTATION_90);
for (int i = 0; i < mButtonDisatchers.size(); i++) {
mButtonDisatchers.valueAt(i).setCurrentView(mCurrentView);
}
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 34aaae452475..fb7afc59b276 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -52,6 +52,7 @@ import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
+import android.hardware.display.DisplayManager;
import android.inputmethodservice.InputMethodService;
import android.media.AudioAttributes;
import android.media.MediaMetadata;
@@ -200,7 +201,7 @@ import static com.android.systemui.statusbar.phone.BarTransitions.MODE_WARNING;
public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
DragDownHelper.DragDownCallback, ActivityStarter, OnUnlockMethodChangedListener,
- HeadsUpManager.OnHeadsUpChangedListener {
+ HeadsUpManager.OnHeadsUpChangedListener, DisplayManager.DisplayListener {
static final String TAG = "PhoneStatusBar";
public static final boolean DEBUG = BaseStatusBar.DEBUG;
public static final boolean SPEW = false;
@@ -684,6 +685,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
mUnlockMethodCache.addListener(this);
startKeyguard();
+ mContext.getSystemService(DisplayManager.class).registerDisplayListener(this, null);
+
mDozeServiceHost = new DozeServiceHost();
KeyguardUpdateMonitor.getInstance(mContext).registerCallback(mDozeServiceHost);
putComponent(DozeHost.class, mDozeServiceHost);
@@ -880,9 +883,9 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
mLightStatusBarController = new LightStatusBarController(mIconController,
mBatteryController);
mKeyguardMonitor = new KeyguardMonitor(mContext);
+ mUserSwitcherController = new UserSwitcherController(mContext, mKeyguardMonitor,
+ mHandler, this);
if (UserManager.get(mContext).isUserSwitcherEnabled()) {
- mUserSwitcherController = new UserSwitcherController(mContext, mKeyguardMonitor,
- mHandler, this);
createUserSwitcher();
}
@@ -3503,6 +3506,21 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
}
@Override
+ public void onDisplayAdded(int displayId) {
+ }
+
+ @Override
+ public void onDisplayRemoved(int displayId) {
+ }
+
+ @Override
+ public void onDisplayChanged(int displayId) {
+ if (displayId == Display.DEFAULT_DISPLAY) {
+ repositionNavigationBar();
+ }
+ }
+
+ @Override
public void userSwitched(int newUserId) {
super.userSwitched(newUserId);
if (MULTIUSER_DEBUG) mNotificationPanelDebugText.setText("USER " + newUserId);
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 85303f422925..21db64febbe0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java
@@ -37,11 +37,11 @@ import com.android.internal.logging.MetricsProto;
import com.android.keyguard.KeyguardStatusView;
import com.android.systemui.FontSizeUtils;
import com.android.systemui.R;
-import com.android.systemui.qs.QSAnimator;
import com.android.systemui.qs.QSPanel;
import com.android.systemui.qs.QSPanel.Callback;
import com.android.systemui.qs.QuickQSPanel;
import com.android.systemui.qs.TouchAnimator;
+import com.android.systemui.qs.TouchAnimator.Builder;
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.NextAlarmController;
import com.android.systemui.statusbar.policy.NextAlarmController.NextAlarmChangeCallback;
@@ -84,13 +84,13 @@ public class QuickStatusBarHeader extends BaseStatusBarHeader implements
private ImageView mMultiUserAvatar;
- private TouchAnimator mSecondHalfAnimator;
- private TouchAnimator mFirstHalfAnimator;
+ private TouchAnimator mAnimator;
protected TouchAnimator mSettingsAlpha;
private float mExpansionAmount;
private QSTileHost mHost;
private View mEdit;
private boolean mShowFullAlarm;
+ private float mDateTimeTranslation;
public QuickStatusBarHeader(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -111,6 +111,7 @@ public class QuickStatusBarHeader extends BaseStatusBarHeader implements
mDateTimeGroup = (ViewGroup) findViewById(R.id.date_time_group);
mDateTimeGroup.setPivotX(0);
mDateTimeGroup.setPivotY(0);
+ mDateTimeTranslation = getResources().getDimension(R.dimen.qs_date_time_translation);
mShowFullAlarm = getResources().getBoolean(R.bool.quick_settings_show_full_alarm);
mExpandIndicator = (ExpandableIndicator) findViewById(R.id.expand_indicator);
@@ -152,15 +153,13 @@ public class QuickStatusBarHeader extends BaseStatusBarHeader implements
FontSizeUtils.updateFontSize(mAlarmStatus, R.dimen.qs_date_collapsed_size);
FontSizeUtils.updateFontSize(mEmergencyOnly, R.dimen.qs_emergency_calls_only_text_size);
- mSecondHalfAnimator = new TouchAnimator.Builder()
+ Builder builder = new Builder()
.addFloat(mShowFullAlarm ? mAlarmStatus : findViewById(R.id.date), "alpha", 0, 1)
- .addFloat(mEmergencyOnly, "alpha", 0, 1)
- .build();
+ .addFloat(mEmergencyOnly, "alpha", 0, 1);
if (mShowFullAlarm) {
- mFirstHalfAnimator = new TouchAnimator.Builder()
- .addFloat(mAlarmStatusCollapsed, "alpha", 1, 0)
- .build();
+ builder.addFloat(mAlarmStatusCollapsed, "alpha", 1, 0);
}
+ mAnimator = builder.build();
updateSettingsAnimator();
}
@@ -223,10 +222,8 @@ public class QuickStatusBarHeader extends BaseStatusBarHeader implements
@Override
public void setExpansion(float headerExpansionFraction) {
mExpansionAmount = headerExpansionFraction;
- mSecondHalfAnimator.setPosition(headerExpansionFraction);
- if (mShowFullAlarm) {
- mFirstHalfAnimator.setPosition(headerExpansionFraction);
- }
+ updateDateTimePosition();
+ mAnimator.setPosition(headerExpansionFraction);
mSettingsAlpha.setPosition(headerExpansionFraction);
updateAlarmVisibilities();
@@ -264,6 +261,7 @@ public class QuickStatusBarHeader extends BaseStatusBarHeader implements
protected void updateVisibilities() {
updateAlarmVisibilities();
+ updateDateTimePosition();
mEmergencyOnly.setVisibility(mExpanded && mShowEmergencyCallsOnly
? View.VISIBLE : View.INVISIBLE);
mSettingsContainer.findViewById(R.id.tuner_icon).setVisibility(
@@ -274,6 +272,11 @@ public class QuickStatusBarHeader extends BaseStatusBarHeader implements
mEdit.setVisibility(isDemo || !mExpanded ? View.INVISIBLE : View.VISIBLE);
}
+ private void updateDateTimePosition() {
+ mDateTimeAlarmGroup.setTranslationY(mShowEmergencyCallsOnly
+ ? mExpansionAmount * mDateTimeTranslation : 0);
+ }
+
private void updateListeners() {
if (mListening) {
mNextAlarmController.addStateChangedCallback(this);
@@ -315,7 +318,8 @@ public class QuickStatusBarHeader extends BaseStatusBarHeader implements
public void onClick(View v) {
if (v == mSettingsButton) {
MetricsLogger.action(mContext,
- MetricsProto.MetricsEvent.ACTION_QS_EXPANDED_SETTINGS_LAUNCH);
+ mExpanded ? MetricsProto.MetricsEvent.ACTION_QS_EXPANDED_SETTINGS_LAUNCH
+ : MetricsProto.MetricsEvent.ACTION_QS_COLLAPSED_SETTINGS_LAUNCH);
if (mSettingsButton.isTunerClick()) {
if (TunerService.isTunerEnabled(mContext)) {
TunerService.showResetRequest(mContext, new Runnable() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ReverseLinearLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ReverseLinearLayout.java
index 3682aa1b06f8..f45967a0a0a6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ReverseLinearLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ReverseLinearLayout.java
@@ -30,7 +30,11 @@ import java.util.ArrayList;
*/
public class ReverseLinearLayout extends LinearLayout {
- private boolean mIsLayoutRtl;
+ /** If true, the layout is reversed vs. a regular linear layout */
+ private boolean mIsLayoutReverse;
+
+ /** If true, the layout is opposite to it's natural reversity from the layout direction */
+ private boolean mIsAlternativeOrder;
public ReverseLinearLayout(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
@@ -39,45 +43,50 @@ public class ReverseLinearLayout extends LinearLayout {
@Override
protected void onFinishInflate() {
super.onFinishInflate();
- mIsLayoutRtl = getResources().getConfiguration()
- .getLayoutDirection() == LAYOUT_DIRECTION_RTL;
+ updateOrder();
}
@Override
public void addView(View child) {
reversParams(child.getLayoutParams());
- if (mIsLayoutRtl) {
- super.addView(child);
- } else {
+ if (mIsLayoutReverse) {
super.addView(child, 0);
+ } else {
+ super.addView(child);
}
}
@Override
public void addView(View child, ViewGroup.LayoutParams params) {
reversParams(params);
- if (mIsLayoutRtl) {
- super.addView(child, params);
- } else {
+ if (mIsLayoutReverse) {
super.addView(child, 0, params);
+ } else {
+ super.addView(child, params);
}
}
@Override
- protected void onConfigurationChanged(Configuration newConfig) {
- super.onConfigurationChanged(newConfig);
- updateRTLOrder();
+ public void onRtlPropertiesChanged(int layoutDirection) {
+ super.onRtlPropertiesChanged(layoutDirection);
+ updateOrder();
+ }
+
+ public void setAlternativeOrder(boolean alternative) {
+ mIsAlternativeOrder = alternative;
+ updateOrder();
}
/**
* In landscape, the LinearLayout is not auto mirrored since it is vertical. Therefore we
* have to do it manually
*/
- private void updateRTLOrder() {
- boolean isLayoutRtl = getResources().getConfiguration()
- .getLayoutDirection() == LAYOUT_DIRECTION_RTL;
- if (mIsLayoutRtl != isLayoutRtl) {
- // RTL changed, swap the order of all views.
+ private void updateOrder() {
+ boolean isLayoutRtl = getLayoutDirection() == LAYOUT_DIRECTION_RTL;
+ boolean isLayoutReverse = isLayoutRtl ^ mIsAlternativeOrder;
+
+ if (mIsLayoutReverse != isLayoutReverse) {
+ // reversity changed, swap the order of all views.
int childCount = getChildCount();
ArrayList<View> childList = new ArrayList<>(childCount);
for (int i = 0; i < childCount; i++) {
@@ -87,7 +96,7 @@ public class ReverseLinearLayout extends LinearLayout {
for (int i = childCount - 1; i >= 0; i--) {
super.addView(childList.get(i));
}
- mIsLayoutRtl = isLayoutRtl;
+ mIsLayoutReverse = isLayoutReverse;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java
index 5d734c682b49..b9c7a4b411ef 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java
@@ -89,14 +89,18 @@ public class BatteryControllerImpl extends BroadcastReceiver implements BatteryC
@Override
public void addStateChangedCallback(BatteryController.BatteryStateChangeCallback cb) {
- mChangeCallbacks.add(cb);
+ synchronized (mChangeCallbacks) {
+ mChangeCallbacks.add(cb);
+ }
cb.onBatteryLevelChanged(mLevel, mPluggedIn, mCharging);
cb.onPowerSaveChanged(mPowerSave);
}
@Override
public void removeStateChangedCallback(BatteryController.BatteryStateChangeCallback cb) {
- mChangeCallbacks.remove(cb);
+ synchronized (mChangeCallbacks) {
+ mChangeCallbacks.remove(cb);
+ }
}
@Override
@@ -171,16 +175,20 @@ public class BatteryControllerImpl extends BroadcastReceiver implements BatteryC
}
protected void fireBatteryLevelChanged() {
- final int N = mChangeCallbacks.size();
- for (int i = 0; i < N; i++) {
- mChangeCallbacks.get(i).onBatteryLevelChanged(mLevel, mPluggedIn, mCharging);
+ synchronized (mChangeCallbacks) {
+ final int N = mChangeCallbacks.size();
+ for (int i = 0; i < N; i++) {
+ mChangeCallbacks.get(i).onBatteryLevelChanged(mLevel, mPluggedIn, mCharging);
+ }
}
}
private void firePowerSaveChanged() {
- final int N = mChangeCallbacks.size();
- for (int i = 0; i < N; i++) {
- mChangeCallbacks.get(i).onPowerSaveChanged(mPowerSave);
+ synchronized (mChangeCallbacks) {
+ final int N = mChangeCallbacks.size();
+ for (int i = 0; i < N; i++) {
+ mChangeCallbacks.get(i).onPowerSaveChanged(mPowerSave);
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
index d8b1a62f49b1..3df759068ae9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
@@ -265,6 +265,11 @@ public class KeyButtonView extends ImageView implements ButtonDispatcher.ButtonI
public void setImageDrawable(@Nullable Drawable drawable) {
super.setImageDrawable(drawable);
}
+
+ @Override
+ public void setLandscape(boolean landscape) {
+ //no op
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/ZenFooter.java b/packages/SystemUI/src/com/android/systemui/volume/ZenFooter.java
index f01e95fa3873..995ecaed6ecf 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/ZenFooter.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/ZenFooter.java
@@ -124,12 +124,8 @@ public class ZenFooter extends LinearLayout {
: null;
Util.setText(mSummaryLine1, line1);
- final boolean isForever = mConfig != null && mConfig.manualRule != null
- && mConfig.manualRule.conditionId == null;
- final CharSequence line2 =
- isForever ? mContext.getString(com.android.internal.R.string.zen_mode_forever_dnd)
- : ZenModeConfig.getConditionSummary(mContext, mConfig, mController.getCurrentUser(),
- true /*shortVersion*/);
+ final CharSequence line2 = ZenModeConfig.getConditionSummary(mContext, mConfig,
+ mController.getCurrentUser(), true /*shortVersion*/);
Util.setText(mSummaryLine2, line2);
}
diff --git a/packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java b/packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java
index 47d1493e1574..97efed0130be 100644
--- a/packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java
+++ b/packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java
@@ -40,22 +40,30 @@ import java.nio.charset.StandardCharsets;
public class WallpaperBackupAgent extends BackupAgent {
private static final String TAG = "WallpaperBackup";
- private static final boolean DEBUG = false;
+ private static final boolean DEBUG = true;
// NB: must be kept in sync with WallpaperManagerService but has no
// compile-time visibility.
// Target filenames within the system's wallpaper directory
static final String WALLPAPER = "wallpaper_orig";
+ static final String WALLPAPER_LOCK = "wallpaper_lock_orig";
static final String WALLPAPER_INFO = "wallpaper_info.xml";
// Names of our local-data stage files/links
static final String IMAGE_STAGE = "wallpaper-stage";
+ static final String LOCK_IMAGE_STAGE = "wallpaper-lock-stage";
static final String INFO_STAGE = "wallpaper-info-stage";
static final String EMPTY_SENTINEL = "empty";
+ static final String QUOTA_SENTINEL = "quota";
- private File mWallpaperInfo; // wallpaper metadata file
- private File mWallpaperFile; // primary wallpaper image file
+ private File mWallpaperInfo; // wallpaper metadata file
+ private File mWallpaperFile; // primary wallpaper image file
+ private File mLockWallpaperFile; // lock wallpaper image file
+
+ // If this file exists, it means we exceeded our quota last time
+ private File mQuotaFile;
+ private boolean mQuotaExceeded;
private WallpaperManager mWm;
@@ -68,7 +76,14 @@ public class WallpaperBackupAgent extends BackupAgent {
File wallpaperDir = Environment.getUserSystemDirectory(UserHandle.USER_SYSTEM);
mWallpaperInfo = new File(wallpaperDir, WALLPAPER_INFO);
mWallpaperFile = new File(wallpaperDir, WALLPAPER);
+ mLockWallpaperFile = new File(wallpaperDir, WALLPAPER_LOCK);
mWm = (WallpaperManager) getSystemService(Context.WALLPAPER_SERVICE);
+
+ mQuotaFile = new File(getFilesDir(), QUOTA_SENTINEL);
+ mQuotaExceeded = mQuotaFile.exists();
+ if (DEBUG) {
+ Slog.v(TAG, "quota file " + mQuotaFile.getPath() + " exists=" + mQuotaExceeded);
+ }
}
@Override
@@ -77,6 +92,7 @@ public class WallpaperBackupAgent extends BackupAgent {
final File filesDir = getFilesDir();
final File infoStage = new File(filesDir, INFO_STAGE);
final File imageStage = new File (filesDir, IMAGE_STAGE);
+ final File lockImageStage = new File (filesDir, LOCK_IMAGE_STAGE);
final File empty = new File (filesDir, EMPTY_SENTINEL);
try {
@@ -96,11 +112,18 @@ public class WallpaperBackupAgent extends BackupAgent {
// In case of prior muddled state
infoStage.delete();
imageStage.delete();
+ lockImageStage.delete();
Os.link(mWallpaperInfo.getCanonicalPath(), infoStage.getCanonicalPath());
fullBackupFile(infoStage, data);
Os.link(mWallpaperFile.getCanonicalPath(), imageStage.getCanonicalPath());
fullBackupFile(imageStage, data);
+
+ // Don't try to store the lock image if we overran our quota last time
+ if (!mQuotaExceeded) {
+ Os.link(mLockWallpaperFile.getCanonicalPath(), lockImageStage.getCanonicalPath());
+ fullBackupFile(lockImageStage, data);
+ }
} else {
if (DEBUG) {
Slog.v(TAG, "Wallpaper not backup-eligible; writing no data");
@@ -114,6 +137,26 @@ public class WallpaperBackupAgent extends BackupAgent {
}
infoStage.delete();
imageStage.delete();
+ lockImageStage.delete();
+
+ // Even if this time we had to back off on attempting to store the lock image
+ // due to exceeding the data quota, try again next time. This will alternate
+ // between "try both" and "only store the primary image" until either there
+ // is no lock image to store, or the quota is raised, or both fit under the
+ // quota.
+ mQuotaFile.delete();
+ }
+ }
+
+ @Override
+ public void onQuotaExceeded(long backupDataBytes, long quotaBytes) {
+ if (DEBUG) {
+ Slog.i(TAG, "Quota exceeded (" + backupDataBytes + " vs " + quotaBytes + ')');
+ }
+ try (FileOutputStream f = new FileOutputStream(mQuotaFile)) {
+ f.write(0);
+ } catch (Exception e) {
+ Slog.w(TAG, "Unable to record quota-exceeded: " + e.getMessage());
}
}
@@ -124,30 +167,17 @@ public class WallpaperBackupAgent extends BackupAgent {
if (DEBUG) {
Slog.v(TAG, "onRestoreFinished()");
}
- final File infoStage = new File(getFilesDir(), INFO_STAGE);
- final File imageStage = new File (getFilesDir(), IMAGE_STAGE);
+ final File filesDir = getFilesDir();
+ final File infoStage = new File(filesDir, INFO_STAGE);
+ final File imageStage = new File (filesDir, IMAGE_STAGE);
+ final File lockImageStage = new File (filesDir, LOCK_IMAGE_STAGE);
try {
// It is valid for the imagery to be absent; it means that we were not permitted
- // to back up the original image on the source device.
- if (imageStage.exists()) {
- if (DEBUG) {
- Slog.v(TAG, "Got restored wallpaper; applying");
- }
-
- // Parse the restored info file to find the crop hint. Note that this currently
- // relies on a priori knowledge of the wallpaper info file schema.
- Rect cropHint = parseCropHint(infoStage);
- if (cropHint != null) {
- if (DEBUG) {
- Slog.v(TAG, "Restored crop hint " + cropHint + "; now writing data");
- }
- WallpaperManager wm = getSystemService(WallpaperManager.class);
- try (FileInputStream in = new FileInputStream(imageStage)) {
- wm.setStream(in, cropHint, true, WallpaperManager.FLAG_SYSTEM);
- } finally {} // auto-closes 'in'
- }
- }
+ // to back up the original image on the source device, or there was no user-supplied
+ // wallpaper image present.
+ restoreFromStage(imageStage, infoStage, "wp", WallpaperManager.FLAG_SYSTEM);
+ restoreFromStage(lockImageStage, infoStage, "kwp", WallpaperManager.FLAG_LOCK);
} catch (Exception e) {
Slog.e(TAG, "Unable to restore wallpaper: " + e.getMessage());
} finally {
@@ -156,10 +186,31 @@ public class WallpaperBackupAgent extends BackupAgent {
}
infoStage.delete();
imageStage.delete();
+ lockImageStage.delete();
+ }
+ }
+
+ private void restoreFromStage(File stage, File info, String hintTag, int which)
+ throws IOException {
+ if (stage.exists()) {
+ if (DEBUG) {
+ Slog.v(TAG, "Got restored wallpaper; applying which=" + which);
+ }
+ // Parse the restored info file to find the crop hint. Note that this currently
+ // relies on a priori knowledge of the wallpaper info file schema.
+ Rect cropHint = parseCropHint(info, hintTag);
+ if (cropHint != null) {
+ if (DEBUG) {
+ Slog.v(TAG, "Restored crop hint " + cropHint + "; now writing data");
+ }
+ try (FileInputStream in = new FileInputStream(stage)) {
+ mWm.setStream(in, cropHint, true, which);
+ } finally {} // auto-closes 'in'
+ }
}
}
- private Rect parseCropHint(File wallpaperInfo) {
+ private Rect parseCropHint(File wallpaperInfo, String sectionTag) {
Rect cropHint = new Rect();
try (FileInputStream stream = new FileInputStream(wallpaperInfo)) {
XmlPullParser parser = Xml.newPullParser();
@@ -170,7 +221,7 @@ public class WallpaperBackupAgent extends BackupAgent {
type = parser.next();
if (type == XmlPullParser.START_TAG) {
String tag = parser.getName();
- if ("wp".equals(tag)) {
+ if (sectionTag.equals(tag)) {
cropHint.left = getAttributeInt(parser, "cropLeft", 0);
cropHint.top = getAttributeInt(parser, "cropTop", 0);
cropHint.right = getAttributeInt(parser, "cropRight", 0);
diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto
index 45e3e7efdcdf..966d0ec44835 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants.proto
@@ -33,73 +33,61 @@ message MetricsEvent {
// OPEN: Settings > Accessibility
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
ACCESSIBILITY = 2;
// OPEN: Settings > Accessibility > Captions
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
ACCESSIBILITY_CAPTION_PROPERTIES = 3;
// OPEN: Settings > Accessibility > [Service]
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
ACCESSIBILITY_SERVICE = 4;
// OPEN: Settings > Accessibility > Color correction
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
ACCESSIBILITY_TOGGLE_DALTONIZER = 5;
// OPEN: Settings > Accessibility > Accessibility shortcut
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
ACCESSIBILITY_TOGGLE_GLOBAL_GESTURE = 6;
// OPEN: Settings > Accessibility > Magnification gestures
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
ACCESSIBILITY_TOGGLE_SCREEN_MAGNIFICATION = 7;
// OPEN: Settings > Accounts
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
ACCOUNT = 8;
// OPEN: Settings > Accounts > [Single Account Sync Settings]
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
ACCOUNTS_ACCOUNT_SYNC = 9;
// OPEN: Settings > Accounts > Add an account
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
ACCOUNTS_CHOOSE_ACCOUNT_ACTIVITY = 10;
// OPEN: Settings > Accounts > [List of accounts when more than one]
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
ACCOUNTS_MANAGE_ACCOUNTS = 11;
// OPEN: Settings > Cellular network settings > APNs
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
APN = 12;
// OPEN: Settings > More > Cellular network settings > APNs > [Edit APN]
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
APN_EDITOR = 13;
// OBSOLETE
@@ -114,7 +102,6 @@ message MetricsEvent {
// OPEN: Settings > Apps > Configure apps > App links > [App]
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
APPLICATIONS_APP_LAUNCH = 17;
// OBSOLETE
@@ -123,19 +110,16 @@ message MetricsEvent {
// OPEN: Settings > Internal storage > Apps storage > [App]
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
APPLICATIONS_APP_STORAGE = 19;
// OPEN: Settings > Apps > [App info]
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
APPLICATIONS_INSTALLED_APP_DETAILS = 20;
// OPEN: Settings > Memory > App usage > [App Memory usage]
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
APPLICATIONS_PROCESS_STATS_DETAIL = 21;
// OBSOLETE
@@ -144,19 +128,16 @@ message MetricsEvent {
// OPEN: Settings > Memory > App usage
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
APPLICATIONS_PROCESS_STATS_UI = 23;
// OPEN: Settings > Bluetooth
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
BLUETOOTH = 24;
// OPEN: Choose Bluetooth device (ex: when sharing)
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
BLUETOOTH_DEVICE_PICKER = 25;
// OBSOLETE
@@ -165,55 +146,46 @@ message MetricsEvent {
// OPEN: Settings > Security > Choose screen lock
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
CHOOSE_LOCK_GENERIC = 27;
// OPEN: Settings > Security > Choose screen lock > Choose your password
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
CHOOSE_LOCK_PASSWORD = 28;
// OPEN: Settings > Security > Choose screen lock > Choose your pattern
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
CHOOSE_LOCK_PATTERN = 29;
// OPEN: Settings > Security > Choose screen lock > Confirm your password
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
CONFIRM_LOCK_PASSWORD = 30;
// OPEN: Settings > Security > Choose screen lock > Confirm your pattern
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
CONFIRM_LOCK_PATTERN = 31;
// OPEN: Settings > Security > Encrypt phone
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
CRYPT_KEEPER = 32;
// OPEN: Settings > Security > Encrypt phone > Confirm
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
CRYPT_KEEPER_CONFIRM = 33;
// OPEN: Settings > Search results
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
DASHBOARD_SEARCH_RESULTS = 34;
// OPEN: Settings (Root page)
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
DASHBOARD_SUMMARY = 35;
// OBSOLETE
@@ -222,49 +194,41 @@ message MetricsEvent {
// OPEN: Settings > Data usage
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
DATA_USAGE_SUMMARY = 37;
// OPEN: Settings > Date & time
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
DATE_TIME = 38;
// OPEN: Settings > Developer options
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
DEVELOPMENT = 39;
// OPEN: Settings > About phone
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
DEVICEINFO = 40;
// OPEN: Settings > About phone > Status > IMEI information
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
DEVICEINFO_IMEI_INFORMATION = 41;
// OPEN: Settings > Internal storage
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
DEVICEINFO_STORAGE = 42;
// OPEN: Settings > About phone > Status > SIM status
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
DEVICEINFO_SIM_STATUS = 43;
// OPEN: Settings > About phone > Status
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
DEVICEINFO_STATUS = 44;
// OBSOLETE
@@ -273,25 +237,21 @@ message MetricsEvent {
// OPEN: Settings > Display
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
DISPLAY = 46;
// OPEN: Settings > Display > Daydream
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
DREAM = 47;
// OPEN: Settings > Security > Screen lock > Secure start-up
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
ENCRYPTION = 48;
// OPEN: Settings > Security > Nexus Imprint
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
FINGERPRINT = 49;
// OBSOLETE
@@ -300,55 +260,46 @@ message MetricsEvent {
// OPEN: Settings > Battery > History details
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
FUELGAUGE_BATTERY_HISTORY_DETAIL = 51;
// OPEN: Settings > Battery > Battery saver
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
FUELGAUGE_BATTERY_SAVER = 52;
// OPEN: Settings > Battery > [App Use details]
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
FUELGAUGE_POWER_USAGE_DETAIL = 53;
// OPEN: Settings > Battery
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
FUELGAUGE_POWER_USAGE_SUMMARY = 54;
// OPEN: Settings > Home
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
HOME = 55;
// OPEN: Settings > Security > SIM card lock settings
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
ICC_LOCK = 56;
// OPEN: Settings > Language & input
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
INPUTMETHOD_LANGUAGE = 57;
// OPEN: Settings > Language & input > Physical keyboard
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
INPUTMETHOD_KEYBOARD = 58;
// OPEN: Settings > Language & input > Spell checker
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
INPUTMETHOD_SPELL_CHECKERS = 59;
// OBSOLETE
@@ -357,79 +308,66 @@ message MetricsEvent {
// OPEN: Settings > Language & input > Personal dictionary
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
INPUTMETHOD_USER_DICTIONARY = 61;
// OPEN: Settings > Language & input > Add word
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
INPUTMETHOD_USER_DICTIONARY_ADD_WORD = 62;
// OPEN: Settings > Location
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
LOCATION = 63;
// OPEN: Settings > Location > Location mode
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
LOCATION_MODE = 64;
// OPEN: Settings > Apps
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
MANAGE_APPLICATIONS = 65;
// OPEN: Settings > Backup & reset > Factory data reset
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
MASTER_CLEAR = 66;
// OPEN: Settings > Backup & reset > Factory data reset > Confirm
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
MASTER_CLEAR_CONFIRM = 67;
// OPEN: Settings > Data usage > Network restrictions
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
NET_DATA_USAGE_METERED = 68;
// OPEN: Settings > More > Android Beam
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
NFC_BEAM = 69;
// OPEN: Settings > Tap & pay
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
NFC_PAYMENT = 70;
// OPEN: Settings > Sound & notification
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
NOTIFICATION = 71;
// OPEN: Settings > Sound & notification > App notifications > [App]
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
NOTIFICATION_APP_NOTIFICATION = 72;
// OPEN: Settings > Sound & notification > Other sounds
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
NOTIFICATION_OTHER_SOUND = 73;
// OBSOLETE
@@ -438,13 +376,11 @@ message MetricsEvent {
// OPEN: Settings Widget > Notification log
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
NOTIFICATION_STATION = 75;
// OPEN: Settings > Sound & notification > Do not disturb
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
NOTIFICATION_ZEN_MODE = 76;
// OPEN: OBSOLETE
@@ -453,25 +389,21 @@ message MetricsEvent {
// OPEN: Print job notification > Print job settings
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
PRINT_JOB_SETTINGS = 78;
// OPEN: Settings > Printing > [Print Service]
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
PRINT_SERVICE_SETTINGS = 79;
// OPEN: Settings > Printing
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
PRINT_SETTINGS = 80;
// OPEN: Settings > Backup & reset
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
PRIVACY = 81;
//OBSOLETE
@@ -480,37 +412,31 @@ message MetricsEvent {
// OPEN: Settings > Backup & reset > Network settings reset
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
RESET_NETWORK = 83;
// OPEN: Settings > Backup & reset > Network settings reset > Confirm
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
RESET_NETWORK_CONFIRM = 84;
// OPEN: Settings > Developer Options > Running Services
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
RUNNING_SERVICE_DETAILS = 85;
// OPEN: Settings > Security > Screen pinning
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
SCREEN_PINNING = 86;
// OPEN: Settings > Security
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
SECURITY = 87;
// OPEN: Settings > SIM cards
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
SIM = 88;
// OBSOLETE
@@ -519,55 +445,46 @@ message MetricsEvent {
// OPEN: Settings > More > Tethering & portable hotspot
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
TETHER = 90;
// OPEN: Settings > Security > Trust agents
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
TRUST_AGENT = 91;
// OPEN: Settings > Security > Trusted credentials
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
TRUSTED_CREDENTIALS = 92;
// OPEN: Settings > Language & input > TTS output > [Engine] > Settings
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
TTS_ENGINE_SETTINGS = 93;
// OPEN: Settings > Language & input > Text-to-speech output
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
TTS_TEXT_TO_SPEECH = 94;
// OPEN: Settings > Security > Apps with usage access
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
USAGE_ACCESS = 95;
// OPEN: Settings > Users
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
USER = 96;
// OPEN: Settings > Users > [Restricted profile app & content access]
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
USERS_APP_RESTRICTIONS = 97;
// OPEN: Settings > Users > [User settings]
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
USER_DETAILS = 98;
// OBSOLETE
@@ -576,43 +493,36 @@ message MetricsEvent {
// OPEN: Settings > More > VPN
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
VPN = 100;
// OPEN: Settings > Display > Choose wallpaper from
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
WALLPAPER_TYPE = 101;
// OPEN: Settings > Display > Cast
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
WFD_WIFI_DISPLAY = 102;
// OPEN: Settings > Wi-Fi
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
WIFI = 103;
// OPEN: Settings > Wi-Fi > Advanced Wi-Fi
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
WIFI_ADVANCED = 104;
// OPEN: Settings > More > Wi-Fi Calling
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
WIFI_CALLING = 105;
// OPEN: Settings > Wi-Fi > Saved networks
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
WIFI_SAVED_ACCESS_POINTS = 106;
// OBSOLETE
@@ -624,19 +534,16 @@ message MetricsEvent {
// OPEN: Settings > Wi-Fi > Advanced Wi-Fi > Wi-Fi Direct
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
WIFI_P2P = 109;
// OPEN: Settings > More
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
WIRELESS = 110;
// OPEN: Quick Settings Panel
// CATEGORY: QUICK_SETTINGS
// OS: 6.0
- // GMS: 7.5.26
QS_PANEL = 111;
// OPEN: QS Airplane mode tile shown
@@ -644,7 +551,6 @@ message MetricsEvent {
// SUBTYPE: 0 is off, 1 is on
// CATEGORY: QUICK_SETTINGS
// OS: 6.0
- // GMS: 7.5.46
QS_AIRPLANEMODE = 112;
// OPEN: QS Bluetooth tile shown
@@ -652,21 +558,18 @@ message MetricsEvent {
// SUBTYPE: 0 is off, 1 is on
// CATEGORY: QUICK_SETTINGS
// OS: 6.0
- // GMS: 7.5.46
QS_BLUETOOTH = 113;
// OPEN: QS Cast tile shown
// ACTION: QS Cast tile tapped
// CATEGORY: QUICK_SETTINGS
// OS: 6.0
- // GMS: 7.5.46
QS_CAST = 114;
// OPEN: QS Cellular tile shown
// ACTION: QS Cellular tile tapped
// CATEGORY: QUICK_SETTINGS
// OS: 6.0
- // GMS: 7.5.46
QS_CELLULAR = 115;
// OPEN: QS Color inversion tile shown
@@ -674,13 +577,11 @@ message MetricsEvent {
// SUBTYPE: 0 is off, 1 is on
// CATEGORY: QUICK_SETTINGS
// OS: 6.0
- // GMS: 7.5.46
QS_COLORINVERSION = 116;
// OPEN: QS Cellular tile > Cellular detail panel
// CATEGORY: QUICK_SETTINGS
// OS: 6.0
- // GMS: 7.5.46
QS_DATAUSAGEDETAIL = 117;
// OPEN: QS Do not disturb tile shown
@@ -688,7 +589,6 @@ message MetricsEvent {
// SUBTYPE: 0 is off, 1 is on
// CATEGORY: QUICK_SETTINGS
// OS: 6.0
- // GMS: 7.5.46
QS_DND = 118;
// OPEN: QS Flashlight tile shown
@@ -696,7 +596,6 @@ message MetricsEvent {
// SUBTYPE: 0 is off, 1 is on
// CATEGORY: QUICK_SETTINGS
// OS: 6.0
- // GMS: 7.5.46
QS_FLASHLIGHT = 119;
// OPEN: QS Hotspot tile shown
@@ -704,14 +603,12 @@ message MetricsEvent {
// SUBTYPE: 0 is off, 1 is on
// CATEGORY: QUICK_SETTINGS
// OS: 6.0
- // GMS: 7.5.46
QS_HOTSPOT = 120;
// OPEN: QS 3P tile shown
// ACTION: QS 3P tile tapped
// CATEGORY: QUICK_SETTINGS
// OS: 6.0
- // GMS: 7.5.46
QS_INTENT = 121;
// OPEN: QS Location tile shown
@@ -719,7 +616,6 @@ message MetricsEvent {
// SUBTYPE: 0 is off, 1 is on
// CATEGORY: QUICK_SETTINGS
// OS: 6.0
- // GMS: 7.5.46
QS_LOCATION = 122;
// OPEN: QS Rotation tile shown
@@ -727,7 +623,6 @@ message MetricsEvent {
// SUBTYPE: 0 is off, 1 is on
// CATEGORY: QUICK_SETTINGS
// OS: 6.0
- // GMS: 7.5.46
QS_ROTATIONLOCK = 123;
// OBSOLETE
@@ -736,7 +631,6 @@ message MetricsEvent {
// OPEN: QS User list panel
// CATEGORY: QUICK_SETTINGS
// OS: 6.0
- // GMS: 7.5.46
QS_USERDETAIL = 125;
// OPEN: QS WiFi tile shown
@@ -744,13 +638,11 @@ message MetricsEvent {
// SUBTYPE: 0 is off, 1 is on
// CATEGORY: QUICK_SETTINGS
// OS: 6.0
- // GMS: 7.5.46
QS_WIFI = 126;
// OPEN: Notification Panel (including lockscreen)
// CATEGORY: NOTIFICATION
// OS: 5.1.1
- // GMS: 7.5.26
NOTIFICATION_PANEL = 127;
// OPEN: Notification in panel became visible.
@@ -764,7 +656,6 @@ message MetricsEvent {
// SUBTYPE: Dismiss reason from NotificationManagerService.java
// CATEGORY: NOTIFICATION
// OS: 5.1.1
- // GMS: 7.5.26
NOTIFICATION_ITEM = 128;
// ACTION: User tapped notification action
@@ -772,19 +663,16 @@ message MetricsEvent {
// SUBTYPE: Index of action on notification
// CATEGORY: NOTIFICATION
// OS: 5.0
- // GMS: 7.5.26
NOTIFICATION_ITEM_ACTION = 129;
// OPEN: Settings > Apps > Configure apps > App permissions
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
APPLICATIONS_ADVANCED = 130;
// OPEN: Settings > Location > Scanning
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
LOCATION_SCANNING = 131;
// OBSOLETE
@@ -793,43 +681,36 @@ message MetricsEvent {
// OPEN: Settings > Sound & notification > App notifications
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
MANAGE_APPLICATIONS_NOTIFICATIONS = 133;
// ACTION: Settings > Wi-Fi > Overflow > Add Network
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
ACTION_WIFI_ADD_NETWORK = 134;
// ACTION: Settings > Wi-Fi > [Long press network] > Connect to network
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
ACTION_WIFI_CONNECT = 135;
// ACTION: Settings > Wi-Fi > Overflow > Refresh
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
ACTION_WIFI_FORCE_SCAN = 136;
// ACTION: Settings > Wi-Fi > [Long press network] > Forget network
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
ACTION_WIFI_FORGET = 137;
// ACTION: Settings > Wi-Fi > Toggle off
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
ACTION_WIFI_OFF = 138;
// ACTION: Settings > Wi-Fi > Toggle on
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
ACTION_WIFI_ON = 139;
// OBSOLETE
@@ -838,280 +719,236 @@ message MetricsEvent {
// OPEN: Settings > Sound & notification > DND > Priority only allows
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
NOTIFICATION_ZEN_MODE_PRIORITY = 141;
// OPEN: Settings > Sound & notification > DND > Automatic rules
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
NOTIFICATION_ZEN_MODE_AUTOMATION = 142;
// OPEN: Settings > Apps > Configure apps > App links
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
MANAGE_DOMAIN_URLS = 143;
// OPEN: Settings > Sound & notification > DND > [Time based rule]
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
NOTIFICATION_ZEN_MODE_SCHEDULE_RULE = 144;
// OPEN: Settings > Sound & notification > DND > [External rule]
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
NOTIFICATION_ZEN_MODE_EXTERNAL_RULE = 145;
// OPEN: Settings > Sound & notification > DND > [Event rule]
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
NOTIFICATION_ZEN_MODE_EVENT_RULE = 146;
// ACTION: App notification settings > Block Notifications
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
ACTION_BAN_APP_NOTES = 147;
// ACTION: Notification shade > Dismiss all button
// CATEGORY: NOTIFICATION
// OS: 6.0
- // GMS: 7.5.26
ACTION_DISMISS_ALL_NOTES = 148;
// OPEN: QS Do Not Disturb detail panel
// CATEGORY: QUICK_SETTINGS
// OS: 6.0
- // GMS: 7.5.26
QS_DND_DETAILS = 149;
// OPEN: QS Bluetooth detail panel
// CATEGORY: QUICK_SETTINGS
// OS: 6.0
- // GMS: 7.5.26
QS_BLUETOOTH_DETAILS = 150;
// OPEN: QS Cast detail panel
// CATEGORY: QUICK_SETTINGS
// OS: 6.0
- // GMS: 7.5.26
QS_CAST_DETAILS = 151;
// OPEN: QS Wi-Fi detail panel
// CATEGORY: QUICK_SETTINGS
// OS: 6.0
- // GMS: 7.5.26
QS_WIFI_DETAILS = 152;
// ACTION: QS Wi-Fi detail panel > Wi-Fi toggle
// SUBTYPE: 0 is off, 1 is on
// CATEGORY: QUICK_SETTINGS
// OS: 6.0
- // GMS: 7.5.26
QS_WIFI_TOGGLE = 153;
// ACTION: QS Bluetooth detail panel > Bluetooth toggle
// SUBTYPE: 0 is off, 1 is on
// CATEGORY: QUICK_SETTINGS
// OS: 6.0
- // GMS: 7.5.26
QS_BLUETOOTH_TOGGLE = 154;
// ACTION: QS Cellular detail panel > Cellular toggle
// SUBTYPE: 0 is off, 1 is on
// CATEGORY: QUICK_SETTINGS
// OS: 6.0
- // GMS: 7.5.26
QS_CELLULAR_TOGGLE = 155;
// ACTION: QS User list panel > Select different user
// CATEGORY: QUICK_SETTINGS
// OS: 6.0
- // GMS: 7.5.26
QS_SWITCH_USER = 156;
// ACTION: QS Cast detail panel > Select cast device
// CATEGORY: QUICK_SETTINGS
// OS: 6.0
- // GMS: 7.5.26
QS_CAST_SELECT = 157;
// ACTION: QS Cast detail panel > Disconnect cast device
// CATEGORY: QUICK_SETTINGS
// OS: 6.0
- // GMS: 7.5.26
QS_CAST_DISCONNECT = 158;
// ACTION: Settings > Bluetooth > Toggle
// SUBTYPE: 0 is off, 1 is on
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
ACTION_BLUETOOTH_TOGGLE = 159;
// ACTION: Settings > Bluetooth > Overflow > Refresh
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
ACTION_BLUETOOTH_SCAN = 160;
// ACTION: Settings > Bluetooth > Overflow > Rename this device
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
ACTION_BLUETOOTH_RENAME = 161;
// ACTION: Settings > Bluetooth > Overflow > Show received files
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
ACTION_BLUETOOTH_FILES = 162;
// ACTION: QS DND details panel > Increase / Decrease exit time
// SUBTYPE: true is increase, false is decrease
// CATEGORY: QUICK_SETTINGS
// OS: 6.0
- // GMS: 7.5.26
QS_DND_TIME = 163;
// ACTION: QS DND details panel > [Exit condition]
// CATEGORY: QUICK_SETTINGS
// OS: 6.0
- // GMS: 7.5.26
QS_DND_CONDITION_SELECT = 164;
// ACTION: QS DND details panel > [DND mode]
// SUBTYPE: 1 is priority, 2 is silence, 3 is alarms only
// CATEGORY: QUICK_SETTINGS
// OS: 6.0
- // GMS: 7.5.26
QS_DND_ZEN_SELECT = 165;
// ACTION: QS DND detail panel > DND toggle
// SUBTYPE: 0 is off, 1 is on
// CATEGORY: QUICK_SETTINGS
// OS: 6.0
- // GMS: 7.5.26
QS_DND_TOGGLE = 166;
// ACTION: DND Settings > Priority only allows > Reminder toggle
// SUBTYPE: 0 is off, 1 is on
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
ACTION_ZEN_ALLOW_REMINDERS = 167;
// ACTION: DND Settings > Priority only allows > Event toggle
// SUBTYPE: 0 is off, 1 is on
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
ACTION_ZEN_ALLOW_EVENTS = 168;
// ACTION: DND Settings > Priority only allows > Messages
// SUBTYPE: 0 is off, 1 is on
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
ACTION_ZEN_ALLOW_MESSAGES = 169;
// ACTION: DND Settings > Priority only allows > Calls
// SUBTYPE: 0 is off, 1 is on
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
ACTION_ZEN_ALLOW_CALLS = 170;
// ACTION: DND Settings > Priority only allows > Repeat callers toggle
// SUBTYPE: 0 is off, 1 is on
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
ACTION_ZEN_ALLOW_REPEAT_CALLS = 171;
// ACTION: DND Settings > Automatic rules > Add rule
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
ACTION_ZEN_ADD_RULE = 172;
// ACTION: DND Settings > Automatic rules > Add rule > OK
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
ACTION_ZEN_ADD_RULE_OK = 173;
// ACTION: DND Settings > Automatic rules > [Rule] > Delete rule
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
ACTION_ZEN_DELETE_RULE = 174;
// ACTION: DND Settings > Automatic rules > [Rule] > Delete rule > Delete
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
ACTION_ZEN_DELETE_RULE_OK = 175;
// ACTION: DND Settings > Automatic rules > [Rule] > Toggle
// SUBTYPE: 0 is off, 1 is on
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
ACTION_ZEN_ENABLE_RULE = 176;
// ACTION: Settings > More > Airplane mode toggle
// SUBTYPE: 0 is off, 1 is on
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
ACTION_AIRPLANE_TOGGLE = 177;
// ACTION: Settings > Data usage > Cellular data toggle
// SUBTYPE: 0 is off, 1 is on
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
ACTION_CELL_DATA_TOGGLE = 178;
// OPEN: Settings > Sound & notification > Notification access
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
NOTIFICATION_ACCESS = 179;
// OPEN: Settings > Sound & notification > Do Not Disturb access
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
NOTIFICATION_ZEN_MODE_ACCESS = 180;
// OPEN: Settings > Apps > Configure apps > Default Apps
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
APPLICATIONS_DEFAULT_APPS = 181;
// OPEN: Settings > Internal storage > Apps storage
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
APPLICATIONS_STORAGE_APPS = 182;
// OPEN: Settings > Security > Usage access
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
APPLICATIONS_USAGE_ACCESS_DETAIL = 183;
// OPEN: Settings > Battery > Battery optimization
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
APPLICATIONS_HIGH_POWER_APPS = 184;
// OBSOLETE
@@ -1120,448 +957,377 @@ message MetricsEvent {
// ACTION: Lockscreen > Unlock gesture
// CATEGORY: GLOBAL_SYSTEM_UI
// OS: 5.1.1
- // GMS: 7.8.22
ACTION_LS_UNLOCK = 186;
// ACTION: Lockscreen > Pull shade open
// CATEGORY: GLOBAL_SYSTEM_UI
// OS: 5.1.1
- // GMS: 7.8.22
ACTION_LS_SHADE = 187;
// ACTION: Lockscreen > Tap on lock, shows hint
// CATEGORY: GLOBAL_SYSTEM_UI
// OS: 5.1.1
- // GMS: 7.8.22
ACTION_LS_HINT = 188;
// ACTION: Lockscreen > Camera
// CATEGORY: GLOBAL_SYSTEM_UI
// OS: 5.1.1
- // GMS: 7.8.22
ACTION_LS_CAMERA = 189;
// ACTION: Lockscreen > Dialer
// CATEGORY: GLOBAL_SYSTEM_UI
// OS: 5.1.1
- // GMS: 7.8.22
ACTION_LS_DIALER = 190;
// ACTION: Lockscreen > Tap on lock, locks phone
// CATEGORY: GLOBAL_SYSTEM_UI
// OS: 5.1.1
- // GMS: 7.8.22
ACTION_LS_LOCK = 191;
// ACTION: Lockscreen > Tap on notification, false touch rejection
// CATEGORY: GLOBAL_SYSTEM_UI
// OS: 5.1.1
- // GMS: 7.8.22
ACTION_LS_NOTE = 192;
// ACTION: Lockscreen > Swipe down to open quick settings
// CATEGORY: GLOBAL_SYSTEM_UI
// OS: 6.0
- // GMS: 7.8.22
ACTION_LS_QS = 193;
// ACTION: Swipe down to open quick settings when unlocked
// CATEGORY: GLOBAL_SYSTEM_UI
// OS: 6.0
- // GMS: 7.8.22
ACTION_SHADE_QS_PULL = 194;
// ACTION: Notification shade > Tap to open quick settings
// CATEGORY: GLOBAL_SYSTEM_UI
// OS: 6.0
- // GMS: 7.8.22
ACTION_SHADE_QS_TAP = 195;
// OPEN: Lockscreen
// SUBTYPE: 0 is unsecure, 1 is secured by password / pattern / PIN
// CATEGORY: GLOBAL_SYSTEM_UI
// OS: 5.1.1
- // GMS: 7.8.22
LOCKSCREEN = 196;
// OPEN: Lockscreen > Screen to enter password / pattern / PIN
// CATEGORY: GLOBAL_SYSTEM_UI
// OS: 5.1.1
- // GMS: 7.8.22
BOUNCER = 197;
// OPEN: Screen turned on
// SUBTYPE: 2 is user action
// CATEGORY: GLOBAL_SYSTEM_UI
// OS: 5.1.1
- // GMS: 7.8.22
SCREEN = 198;
// OPEN: Notification caused sound, vibration, and/or LED blink
// SUBTYPE: 1 is buzz, 2 is beep, blink is 4, or'd together
// CATEGORY: NOTIFICATION
// OS: 5.1.1
- // GMS: 7.8.53
NOTIFICATION_ALERT = 199;
// ACTION: Lockscreen > Emergency Call button
// CATEGORY: GLOBAL_SYSTEM_UI
// OS: 5.1.1
- // GMS: 7.5.26
ACTION_EMERGENCY_CALL = 200;
// OPEN: Settings > Apps > Configure > Default apps > Assist & voice input
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
APPLICATIONS_MANAGE_ASSIST = 201;
// OPEN: Settings > Memory
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
PROCESS_STATS_SUMMARY = 202;
// ACTION: Settings > Display > When device is rotated
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
ACTION_ROTATION_LOCK = 203;
// ACTION: Long press on notification to view controls
// CATEGORY: NOTIFICATION
// OS: 6.0
- // GMS: 7.5.26
ACTION_NOTE_CONTROLS = 204;
// ACTION: Notificatoin controls > Info button
// CATEGORY: NOTIFICATION
// OS: 6.0
- // GMS: 7.5.26
ACTION_NOTE_INFO = 205;
// ACTION: Notification controls > Settings button
// CATEGORY: NOTIFICATION
// OS: 6.0
- // GMS: 7.5.26
ACTION_APP_NOTE_SETTINGS = 206;
// OPEN: Volume Dialog (with hardware buttons)
// CATEGORY: GLOBAL_SYSTEM_UI
// OS: 6.0
- // GMS: 7.5.26
VOLUME_DIALOG = 207;
// OPEN: Volume dialog > Expanded volume dialog (multiple sliders)
// CATEGORY: GLOBAL_SYSTEM_UI
// OS: 6.0
- // GMS: 7.5.26
VOLUME_DIALOG_DETAILS = 208;
// ACTION: Volume dialog > Adjust volume slider
// SUBTYPE: volume level (0-7)
// CATEGORY: GLOBAL_SYSTEM_UI
// OS: 6.0
- // GMS: 7.5.26
ACTION_VOLUME_SLIDER = 209;
// ACTION: Volume dialog > Select non-active stream
// SUBTYPE: stream (defined in AudioSystem.java)
// CATEGORY: GLOBAL_SYSTEM_UI
// OS: 6.0
- // GMS: 7.5.26
ACTION_VOLUME_STREAM = 210;
// ACTION: Adjust volume with hardware key
// SUBTYPE: volume level (0-7)
// CATEGORY: GLOBAL_SYSTEM_UI
// OS: 6.0
- // GMS: 7.5.26
ACTION_VOLUME_KEY = 211;
// ACTION: Volume dialog > Mute a stream by tapping icon
// SUBTYPE: mute is 1, audible is 2
// CATEGORY: GLOBAL_SYSTEM_UI
// OS: 6.0
- // GMS: 7.5.26
ACTION_VOLUME_ICON = 212;
// ACTION: Volume dialog > Change ringer mode by tapping icon
// SUBTYPE: 2 is audible, 3 is vibrate
// CATEGORY: GLOBAL_SYSTEM_UI
// OS: 6.0
- // GMS: 7.5.26
ACTION_RINGER_MODE = 213;
// ACTION: Chooser shown (share target, file open, etc.)
// CATEGORY: GLOBAL_SYSTEM_UI
// OS: 6.0
- // GMS: 7.5.26
ACTION_ACTIVITY_CHOOSER_SHOWN = 214;
// ACTION: Chooser > User taps an app target
// SUBTYPE: Index of target
// CATEGORY: GLOBAL_SYSTEM_UI
// OS: 6.0
- // GMS: 7.5.26
ACTION_ACTIVITY_CHOOSER_PICKED_APP_TARGET = 215;
// ACTION: Chooser > User taps a service target
// SUBTYPE: Index of target
// CATEGORY: GLOBAL_SYSTEM_UI
// OS: 6.0
- // GMS: 7.5.26
ACTION_ACTIVITY_CHOOSER_PICKED_SERVICE_TARGET = 216;
// ACTION: Chooser > User taps a standard target
// SUBTYPE: Index of target
// CATEGORY: GLOBAL_SYSTEM_UI
// OS: 6.0
- // GMS: 7.5.26
ACTION_ACTIVITY_CHOOSER_PICKED_STANDARD_TARGET = 217;
// ACTION: QS Brightness Slider (with auto brightness disabled)
// SUBTYPE: slider value
// CATEGORY: QUICK_SETTINGS
// OS: 6.0
- // GMS: 7.5.26
ACTION_BRIGHTNESS = 218;
// ACTION: QS Brightness Slider (with auto brightness enabled)
// SUBTYPE: slider value
// CATEGORY: QUICK_SETTINGS
// OS: 6.0
- // GMS: 7.5.26
ACTION_BRIGHTNESS_AUTO = 219;
// OPEN: Settings > Display > Brightness Slider
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
BRIGHTNESS_DIALOG = 220;
// OPEN: Settings > Apps > Configure Apps > Draw over other apps
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
SYSTEM_ALERT_WINDOW_APPS = 221;
// OPEN: Display has entered dream mode
// CATEGORY: GLOBAL_SYSTEM_UI
// OS: 6.0
- // GMS: 7.5.26
DREAMING = 222;
// OPEN: Display has entered ambient notification mode
// CATEGORY: GLOBAL_SYSTEM_UI
// OS: 6.0
- // GMS: 7.5.26
DOZING = 223;
// OPEN: Overview
// CATEGORY: GLOBAL_SYSTEM_UI
// OS: 6.0
- // GMS: 7.5.26
OVERVIEW_ACTIVITY = 224;
// OPEN: Settings > About phone > Legal information
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
ABOUT_LEGAL_SETTINGS = 225;
// OPEN: Settings > Search > Perform search
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
ACTION_SEARCH_RESULTS = 226;
// OPEN: Settings > System UI Tuner
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
TUNER = 227;
// OPEN: Settings > System UI Tuner > Quick Settings
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
TUNER_QS = 228;
// OPEN: Settings > System UI Tuner > Demo mode
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
TUNER_DEMO_MODE = 229;
// ACTION: Settings > System UI Tuner > Quick Settings > Move tile
// PACKAGE: Tile
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
TUNER_QS_REORDER = 230;
// ACTION: Settings > System UI Tuner > Quick Settings > Add tile
// PACKAGE: Tile
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
TUNER_QS_ADD = 231;
// ACTION: Settings > System UI Tuner > Quick Settings > Remove tile
// PACKAGE: Tile
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
TUNER_QS_REMOVE = 232;
// ACTION: Settings > System UI Tuner > Status bar > Enable icon
// PACKAGE: Icon
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
TUNER_STATUS_BAR_ENABLE = 233;
// ACTION: Settings > System UI Tuner > Status bar > Disable icon
// PACKAGE: Icon
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
TUNER_STATUS_BAR_DISABLE = 234;
// ACTION: Settings > System UI Tuner > Demo mode > Enable demo mode
// SUBTYPE: false is disabled, true is enabled
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
TUNER_DEMO_MODE_ENABLED = 235;
// ACTION: Settings > System UI Tuner > Demo mode > Show demo mode
// SUBTYPE: false is disabled, true is enabled
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
TUNER_DEMO_MODE_ON = 236;
// ACTION: Settings > System UI Tuner > Show embedded battery percentage
// SUBTYPE: 0 is disabled, 1 is enabled
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
TUNER_BATTERY_PERCENTAGE = 237;
// OPEN: Settings > Developer options > Inactive apps
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
FUELGAUGE_INACTIVE_APPS = 238;
// ACTION: Long press home to bring up assistant
// CATEGORY: GLOBAL_SYSTEM_UI
// OS: 6.0
- // GMS: 7.5.26
ACTION_ASSIST_LONG_PRESS = 239;
// OPEN: Settings > Security > Nexus Imprint > Add Fingerprint
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.8.99
FINGERPRINT_ENROLLING = 240;
// OPEN: Fingerprint Enroll > Find Sensor
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.8.99
FINGERPRINT_FIND_SENSOR = 241;
// OPEN: Fingerprint Enroll > Fingerprint Enrolled!
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.8.99
FINGERPRINT_ENROLL_FINISH = 242;
// OPEN: Fingerprint Enroll introduction
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.8.99
FINGERPRINT_ENROLL_INTRO = 243;
// OPEN: Fingerprint Enroll onboarding
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.8.99
FINGERPRINT_ENROLL_ONBOARD = 244;
// OPEN: Fingerprint Enroll > Let's Start!
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.8.99
FINGERPRINT_ENROLL_SIDECAR = 245;
// OPEN: Fingerprint Enroll SUW > Let's Start!
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.8.99
FINGERPRINT_ENROLLING_SETUP = 246;
// OPEN: Fingerprint Enroll SUW > Find Sensor
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.8.99
FINGERPRINT_FIND_SENSOR_SETUP = 247;
// OPEN: Fingerprint Enroll SUW > Fingerprint Enrolled!
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.8.99
FINGERPRINT_ENROLL_FINISH_SETUP = 248;
// OPEN: Fingerprint Enroll SUW introduction
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.8.99
FINGERPRINT_ENROLL_INTRO_SETUP = 249;
// OPEN: Fingerprint Enroll SUW onboarding
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.8.99
FINGERPRINT_ENROLL_ONBOARD_SETUP = 250;
// ACTION: Add fingerprint > Enroll fingerprint
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.8.99
ACTION_FINGERPRINT_ENROLL = 251;
// ACTION: Authenticate using fingerprint
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.8.99
ACTION_FINGERPRINT_AUTH = 252;
// ACTION: Settings > Security > Nexus Imprint > [Fingerprint] > Delete
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.8.99
ACTION_FINGERPRINT_DELETE = 253;
// ACTION: Settings > Security > Nexus Imprint > [Fingerprint] > Rename
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.8.99
ACTION_FINGERPRINT_RENAME = 254;
// ACTION: Double tap camera shortcut
// CATEGORY: GLOBAL_SYSTEM_UI
// OS: 6.0
- // GMS: 7.8.99
ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE = 255;
// ACTION: Double twist camera shortcut
// CATEGORY: GLOBAL_SYSTEM_UI
// OS: 6.0
- // GMS: 7.8.99
ACTION_WIGGLE_CAMERA_GESTURE = 256;
// OPEN: QS Work Mode tile shown
@@ -1569,13 +1335,11 @@ message MetricsEvent {
// SUBTYPE: 0 is off, 1 is on
// CATEGORY: QUICK_SETTINGS
// OS: N
- // GMS: 7.8.99
QS_WORKMODE = 257;
// OPEN: Settings > Developer Options > Background Check
// CATEGORY: SETTINGS
// OS: N
- // GMS: 7.8.99
BACKGROUND_CHECK_SUMMARY = 258;
// OPEN: QS Lock tile shown
@@ -1583,52 +1347,44 @@ message MetricsEvent {
// SUBTYPE: 0 is off, 1 is on
// CATEGORY: QUICK_SETTINGS
// OS: N
- // GMS: 7.8.99
QS_LOCK_TILE = 259;
// OPEN: QS User Tile shown
// CATEGORY: QUICK_SETTINGS
// OS: N
- // GMS: 7.8.99
QS_USER_TILE = 260;
// OPEN: QS Battery tile shown
// CATEGORY: QUICK_SETTINGS
// OS: N
- // GMS: 7.8.99
QS_BATTERY_TILE = 261;
// OPEN: Settings > Sound > Do not disturb > Visual interruptions
// CATEGORY: SETTINGS
// OS: N
- // GMS: 7.8.99
NOTIFICATION_ZEN_MODE_VISUAL_INTERRUPTIONS = 262;
// ACTION: Visual interruptions > No screen interuptions toggle
// SUBTYPE: 0 is off, 1 is on
// CATEGORY: SETTINGS
// OS: N
- // GMS: 7.8.99
ACTION_ZEN_ALLOW_WHEN_SCREEN_OFF = 263;
// ACTION: Visual interruptions > No notification light toggle
// SUBTYPE: 0 is off, 1 is on
// CATEGORY: SETTINGS
// OS: N
- // GMS: 7.8.99
ACTION_ZEN_ALLOW_LIGHTS = 264;
// OPEN: Settings > Notifications > [App] > Topic Notifications
// CATEGORY: SETTINGS
// OS: N
- // GMS: 7.8.99
NOTIFICATION_TOPIC_NOTIFICATION = 265;
// ACTION: Settings > Apps > Default Apps > Select different SMS app
// PACKAGE: Selected SMS app
// CATEGORY: SETTINGS
// OS: N
- // GMS: 7.8.99
ACTION_DEFAULT_SMS_APP_CHANGED = 266;
// OPEN: QS Color modification tile shown
@@ -1636,105 +1392,88 @@ message MetricsEvent {
// SUBTYPE: 0 is off, 1 is on
// CATEGORY: QUICK_SETTINGS
// OS: N
- // GMS: 7.8.99
QS_COLOR_MATRIX = 267;
// OPEN: QS Custom tile shown
// ACTION: QS Work Mode tile tapped
// CATEGORY: QUICK_SETTINGS
// OS: N
- // GMS: 7.8.99
QS_CUSTOM = 268;
// ACTION: Visual interruptions > Never turn off the screen toggle
// SUBTYPE: 0 is off, 1 is on
// CATEGORY: SETTINGS
// OS: N
- // GMS: 7.8.99
ACTION_ZEN_ALLOW_WHEN_SCREEN_ON = 269;
// ACTION: Overview > Long-press task, drag to enter split-screen
// CATEGORY: GLOBAL_SYSTEM_UI
// OS: N
- // GMS: 7.8.99
ACTION_WINDOW_DOCK_DRAG_DROP = 270;
// ACTION: In App > Long-press Overview button to enter split-screen
// CATEGORY: GLOBAL_SYSTEM_UI
// OS: N
- // GMS: 7.8.99
ACTION_WINDOW_DOCK_LONGPRESS = 271;
// ACTION: In App > Swipe Overview button to enter split-screen
// CATEGORY: GLOBAL_SYSTEM_UI
// OS: N
- // GMS: 7.8.99
ACTION_WINDOW_DOCK_SWIPE = 272;
// ACTION: Launch profile-specific app > Confirm credentials
// CATEGORY: GLOBAL_SYSTEM_UI
// OS: N
- // GMS: 7.8.99
PROFILE_CHALLENGE = 273;
// OPEN: QS Battery detail panel
// CATEGORY: GLOBAL_SYSTEM_UI
// OS: N
- // GMS: 7.8.99
QS_BATTERY_DETAIL = 274;
// OPEN: Overview > History
// CATEGORY: GLOBAL_SYSTEM_UI
// OS: N
- // GMS: 7.8.99
OVERVIEW_HISTORY = 275;
// ACTION: Overview > Page by tapping Overview button
// CATEGORY: GLOBAL_SYSTEM_UI
// OS: N
- // GMS: 7.8.99
ACTION_OVERVIEW_PAGE = 276;
// ACTION: Overview > Select app
// CATEGORY: GLOBAL_SYSTEM_UI
// OS: N
- // GMS: 7.8.99
ACTION_OVERVIEW_SELECT = 277;
// ACTION: View emergency info
// CATEGORY: GLOBAL_SYSTEM_UI
// OS: N
- // GMS: 7.8.99
ACTION_VIEW_EMERGENCY_INFO = 278;
// ACTION: Edit emergency info activity
// CATEGORY: SETTINGS
// OS: N
- // GMS: 7.8.99
ACTION_EDIT_EMERGENCY_INFO = 279;
// ACTION: Edit emergency info field
// CATEGORY: SETTINGS
// OS: N
- // GMS: 7.8.99
ACTION_EDIT_EMERGENCY_INFO_FIELD = 280;
// ACTION: Add emergency contact
// CATEGORY: SETTINGS
// OS: N
- // GMS: 7.8.99
ACTION_ADD_EMERGENCY_CONTACT = 281;
// ACTION: Delete emergency contact
// CATEGORY: SETTINGS
// OS: N
- // GMS: 7.8.99
ACTION_DELETE_EMERGENCY_CONTACT = 282;
// ACTION: Call emergency contact
// CATEGORY: SETTINGS
// OS: N
- // GMS: 7.8.99
ACTION_CALL_EMERGENCY_CONTACT = 283;
// OPEN: QS Data Saver tile shown
@@ -1745,13 +1484,11 @@ message MetricsEvent {
// OPEN: Settings > Security > User credentials
// CATEGORY: Settings
// OS: N
- // GMS: 7.8.99
USER_CREDENTIALS = 285;
// ACTION: In App (splitscreen) > Long-press Overview to exit split-screen
// CATEGORY: GLOBAL_SYSTEM_UI
// OS: N
- // GMS: 7.8.99
ACTION_WINDOW_UNDOCK_LONGPRESS = 286;
// Logged when the user scrolls through overview manually
@@ -1773,81 +1510,68 @@ message MetricsEvent {
// ACTION: Long-press power button, then tap "Take bug report" option.
// CATEGORY: GLOBAL_SYSTEM_UI
// OS: N
- // GMS: 7.8.99
ACTION_BUGREPORT_FROM_POWER_MENU_INTERACTIVE = 292;
// ACTION: Long-press power button, then long-press "Take bug report" option.
// CATEGORY: GLOBAL_SYSTEM_UI
// OS: N
- // GMS: 7.8.99
ACTION_BUGREPORT_FROM_POWER_MENU_FULL = 293;
// ACTION: Settings -> Developer Options -> Take bug report -> Interactive report
// CATEGORY: SETTINGS
// OS: N
- // GMS: 7.8.99
// Interactive bug report initiated from Settings.
ACTION_BUGREPORT_FROM_SETTINGS_INTERACTIVE = 294;
// ACTION: Settings -> Developer Options -> Take bug report -> Full report
// CATEGORY: SETTINGS
// OS: N
- // GMS: 7.8.99
// Interactive bug report initiated from Settings.
ACTION_BUGREPORT_FROM_SETTINGS_FULL = 295;
// ACTION: User tapped notification action to cancel a bug report
// CATEGORY: NOTIFICATION
// OS: N
- // GMS: 7.8.99
ACTION_BUGREPORT_NOTIFICATION_ACTION_CANCEL = 296;
// ACTION: User tapped notification action to launch bug report details screen
// CATEGORY: NOTIFICATION
// OS: N
- // GMS: 7.8.99
ACTION_BUGREPORT_NOTIFICATION_ACTION_DETAILS = 297;
// ACTION: User tapped notification action to take adition screenshot on bug report
// CATEGORY: NOTIFICATION
// OS: N
- // GMS: 7.8.99
ACTION_BUGREPORT_NOTIFICATION_ACTION_SCREENSHOT = 298;
// ACTION: User tapped notification to share bug report
// CATEGORY: NOTIFICATION
// OS: N
- // GMS: 7.8.99
ACTION_BUGREPORT_NOTIFICATION_ACTION_SHARE = 299;
// ACTION: User changed bug report name using the details screen
// CATEGORY: GLOBAL_SYSTEM_UI
// OS: N
- // GMS: 7.8.99
ACTION_BUGREPORT_DETAILS_NAME_CHANGED = 300;
// ACTION: User changed bug report title using the details screen
// CATEGORY: GLOBAL_SYSTEM_UI
// OS: N
- // GMS: 7.8.99
ACTION_BUGREPORT_DETAILS_TITLE_CHANGED = 301;
// ACTION: User changed bug report description using the details screen
// CATEGORY: GLOBAL_SYSTEM_UI
// OS: N
- // GMS: 7.8.99
ACTION_BUGREPORT_DETAILS_DESCRIPTION_CHANGED = 302;
// ACTION: User tapped Save in the bug report details screen.
// CATEGORY: GLOBAL_SYSTEM_UI
// OS: N
- // GMS: 7.8.99
ACTION_BUGREPORT_DETAILS_SAVED = 303;
// ACTION: User tapped Cancel in the bug report details screen.
// CATEGORY: GLOBAL_SYSTEM_UI
// OS: N
- // GMS: 7.8.99
ACTION_BUGREPORT_DETAILS_CANCELED = 304;
// Tuner: Open/close calibrate dialog.
@@ -1920,79 +1644,140 @@ message MetricsEvent {
// the transition was executed.
APP_TRANSITION_DEVICE_UPTIME_SECONDS = 325;
- // User granted access to the request folder; action takes an integer
- // representing the folder's index on Environment.STANDARD_DIRECTORIES
- // (or -2 for root access, or -1 or unknown directory).
+ // ACTION: app requested access to a scoped directory, user granted it.
+ // SUBTYPE: directory's index on Environment.STANDARD_DIRECTORIES
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: N
ACTION_SCOPED_DIRECTORY_ACCESS_GRANTED_BY_FOLDER = 326;
- // User denied access to the request folder; action takes an integer
- // representing the folder's index on Environment.STANDARD_DIRECTORIES
- // (or -2 for root access, or -1 or unknown directory).
+ // ACTION: app requested access to a scoped directory, user denied it.
+ // SUBTYPE: directory's index on Environment.STANDARD_DIRECTORIES
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: N
ACTION_SCOPED_DIRECTORY_ACCESS_DENIED_BY_FOLDER = 327;
- // User granted access to the request folder; action pass package name
- // of calling package.
+ // ACTION: app requested access to a scoped directory, user granted it.
+ // PACKAGE: app that requested access
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: N
ACTION_SCOPED_DIRECTORY_ACCESS_GRANTED_BY_PACKAGE = 328;
- // User denied access to the request folder; action pass package name
- // of calling package.
+ // ACTION: app requested access to a scoped directory, user denied it.
+ // PACKAGE: app that requested access.
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: N
ACTION_SCOPED_DIRECTORY_ACCESS_DENIED_BY_PACKAGE = 329;
- // App requested access to a directory it has already been granted
- // access before; action takes an integer representing the folder's
- // index on Environment.STANDARD_DIRECTORIES
- // (or -2 for root access, or -1 or unknown directory).
+ // ACTION: app requested access to a directory user has already been granted
+ // access before.
+ // SUBTYPE: directory's index on Environment.STANDARD_DIRECTORIES.
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: N
ACTION_SCOPED_DIRECTORY_ACCESS_ALREADY_GRANTED_BY_FOLDER = 330;
- // App requested access to a directory it has already been granted
- // access before; action pass package name of calling package.
+ // ACTION: app requested access to a directory user has already been granted
+ // access before.
+ // PACKAGE: app that requested access.
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: N
ACTION_SCOPED_DIRECTORY_ACCESS_ALREADY_GRANTED_BY_PACKAGE = 331;
- // Logged when the user slides a notification and
- // reveals the gear beneath it.
+ // ACTION: Logged when the user slides a notification and reveals the gear
+ // beneath it.
+ // CATEGORY: NOTIFICATION
+ // OS: N
ACTION_REVEAL_GEAR = 332;
- // Logged when the user taps on the gear beneath
- // a notification.
+ // ACTION: Logged when the user taps on the gear beneath a notification.
+ // CATEGORY: NOTIFICATION
+ // OS: N
ACTION_TOUCH_GEAR = 333;
// Logs that the user has edited the enabled VR listeners.
+ // CATEGORY: SETTINGS
+ // OS: N
VR_MANAGE_LISTENERS = 334;
// Settings -> Accessibility -> Click after pointer stops moving
+ // CATEGORY: SETTINGS
+ // OS: N
ACCESSIBILITY_TOGGLE_AUTOCLICK = 335;
+
// Settings -> Sound
+ // CATEGORY: SETTINGS
+ // OS: N
SOUND = 336;
+
// Settings -> Notifications -> Gear
+ // CATEGORY: SETTINGS
+ // OS: N
CONFIGURE_NOTIFICATION = 337;
+
// Settings -> Wi-Fi -> Gear
+ // CATEGORY: SETTINGS
+ // OS: N
CONFIGURE_WIFI = 338;
+
// Settings -> Display -> Display size
+ // OS: N
DISPLAY_SCREEN_ZOOM = 339;
+
// Settings -> Display -> Font size
+ // CATEGORY: SETTINGS
+ // OS: N
ACCESSIBILITY_FONT_SIZE = 340;
+
// Settings -> Data usage -> Cellular/Wi-Fi data usage
+ // CATEGORY: SETTINGS
+ // OS: N
DATA_USAGE_LIST = 341;
+
// Settings -> Data usage -> Billing cycle or DATA_USAGE_LIST -> Gear
+ // CATEGORY: SETTINGS
+ // OS: N
BILLING_CYCLE = 342;
+
// DATA_USAGE_LIST -> Any item or App info -> Data usage
+ // CATEGORY: SETTINGS
+ // OS: N
APP_DATA_USAGE = 343;
+
// Settings -> Language & input -> Language
+ // CATEGORY: SETTINGS
+ // OS: N
USER_LOCALE_LIST = 344;
+
// Settings -> Language & input -> Virtual keyboard
+ // CATEGORY: SETTINGS
+ // OS: N
VIRTUAL_KEYBOARDS = 345;
+
// Settings -> Language & input -> Physical keyboard
+ // CATEGORY: SETTINGS
+ // OS: N
PHYSICAL_KEYBOARDS = 346;
+
// Settings -> Language & input -> Virtual keyboard -> Add a virtual keyboard
+ // CATEGORY: SETTINGS
+ // OS: N
ENABLE_VIRTUAL_KEYBOARDS = 347;
+
// Settings -> Data usage -> Data Saver
+ // CATEGORY: SETTINGS
+ // OS: N
DATA_SAVER_SUMMARY = 348;
+
// Settings -> Data usage -> Data Saver -> Unrestricted data access
+ // CATEGORY: SETTINGS
+ // OS: N
DATA_USAGE_UNRESTRICTED_ACCESS = 349;
// Used for generic logging of Settings Preference Persistence, should not be used
// outside SharedPreferencesLogger.
+ // CATEGORY: SETTINGS
+ // OS: N
ACTION_GENERIC_PACKAGE = 350;
+
// Settings -> Apps -> Gear -> Special access
SPECIAL_ACCESS = 351;
@@ -2158,15 +1943,28 @@ message MetricsEvent {
// System UI Tuner > Other > Power notification controls > Toggle on/off
ACTION_TUNER_POWER_NOTIFICATION_CONTROLS = 393;
- // Action: user enable / disabled data saver using Settings. Arguments:
- // 0: Data Saver mode is disabled.
- // 1: Data Saver mode is enabled.
+ // Action: user enable / disabled data saver using Settings
+ // OPEN: Settings -> Data Usage -> Data saver -> On/off toggle
+ // VALUE: 1 for enabled, 0 for disabled
+ // CATEGORY: SETTINGS
+ // OS: N
ACTION_DATA_SAVER_MODE = 394;
- // User whitelisted an app for Data Saver mode; action pass package name of app.
+ // User whitelisted an app for Data Saver mode; action pass package name of app
+ // Action: user enable / disabled data saver using Settings
+ // OPEN: Settings -> Data Usage -> Data saver -> Unrestricted data access > APP toggle turned on
+ // or
+ // Settings -> Apps -> APP -> Data usage -> Unrestricted data usage toggle turned on
+ // VALUE: package name of APP
+ // CATEGORY: SETTINGS
+ // OS: N
ACTION_DATA_SAVER_WHITELIST = 395;
- // User blacklisted an app for Data Saver mode; action pass package name of app.
+ // User blacklisted an app for Data Saver mode; action pass package name of app
+ // OPEN: Settings -> Apps -> APP -> Data usage -> Background data toggle turned off
+ // VALUE: package name of APP
+ // CATEGORY: SETTINGS
+ // OS: N
ACTION_DATA_SAVER_BLACKLIST = 396;
// User opened a remote input view associated with a notification. Passes package name of app
@@ -2332,45 +2130,64 @@ message MetricsEvent {
SUPPORT_FRAGMENT = 475;
// ACTION: Settings -> Select summary tab.
+ // CATEGORY: SETTINGS
ACTION_SELECT_SUMMARY=476;
// ACTION: Settings -> Select support tab.
+ // CATEGORY: SETTINGS
ACTION_SELECT_SUPPORT_FRAGMENT = 477;
// ACTION: Settings -> Support -> Tips & tricks
+ // CATEGORY: SETTINGS
ACTION_SUPPORT_TIPS_AND_TRICKS = 478;
// ACTION: Settings -> Support -> Help & feedback
+ // CATEGORY: SETTINGS
ACTION_SUPPORT_HELP_AND_FEEDBACK = 479;
// ACTION: Settings -> Support -> Sign in
+ // CATEGORY: SETTINGS
ACTION_SUPPORT_SIGN_IN = 480;
// ACTION: Settings -> Support -> Phone
+ // CATEGORY: SETTINGS
ACTION_SUPPORT_PHONE = 481;
// ACTION: Settings -> Support -> Chat
+ // CATEGORY: SETTINGS
ACTION_SUPPORT_CHAT = 482;
// ACTION: Settings -> Support -> Phone/Chat -> Disclaimer Cancel
+ // CATEGORY: SETTINGS
ACTION_SUPPORT_DISCLAIMER_CANCEL = 483;
// ACTION: Settings -> Support -> Phone/Chat -> Disclaimer OK
+ // CATEGORY: SETTINGS
ACTION_SUPPORT_DISCLAIMER_OK = 484;
// ACTION: Settings -> Support -> Toll-Free Phone
+ // CATEGORY: SETTINGS
ACTION_SUPPORT_DAIL_TOLLFREE = 485;
// ACTION: Settings -> Support -> "Travel Abroad" Button
+ // CATEGORY: SETTINGS
ACTION_SUPPORT_VIEW_TRAVEL_ABROAD_DIALOG = 486;
// ACTION: Settings -> Support -> "Travel Abroad" Button -> Tolled Phone
+ // CATEGORY: SETTINGS
ACTION_SUPPORT_DIAL_TOLLED = 487;
// OPEN: Settings > Display > Night display
// CATEGORY: SETTINGS
NIGHT_DISPLAY_SETTINGS = 488;
+ // ACTION: Settings -> Storage -> Manage storage -> Click Storage Manager
+ // SUBTYPE: false is off, true is on
+ ACTION_TOGGLE_STORAGE_MANAGER = 489;
+
+ // Settings launched from collapsed quick settings.
+ ACTION_QS_COLLAPSED_SETTINGS_LAUNCH = 490;
+
// ---- End N-MR1 Constants, all N-MR1 constants go above this line ----
// Add new aosp constants above this line.
// END OF AOSP CONSTANTS
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index 0b85198d1c2a..5ce8c9e6e4cb 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -797,7 +797,7 @@ public class BackupManagerService {
queue, oldJournal, null, null, false);
Message pbtMessage = obtainMessage(MSG_BACKUP_RESTORE_STEP, pbt);
sendMessage(pbtMessage);
- } catch (RemoteException e) {
+ } catch (Exception e) {
// unable to ask the transport its dir name -- transient failure, since
// the above check succeeded. Try again next time.
Slog.e(TAG, "Transport became unavailable attempting backup");
@@ -940,7 +940,7 @@ public class BackupManagerService {
}
if (sets == null) EventLog.writeEvent(EventLogTags.RESTORE_TRANSPORT_FAILURE);
} catch (Exception e) {
- Slog.e(TAG, "Error from transport getting set list");
+ Slog.e(TAG, "Error from transport getting set list: " + e.getMessage());
} finally {
if (params.observer != null) {
try {
@@ -948,7 +948,7 @@ public class BackupManagerService {
} catch (RemoteException re) {
Slog.e(TAG, "Unable to report listing to observer");
} catch (Exception e) {
- Slog.e(TAG, "Restore observer threw", e);
+ Slog.e(TAG, "Restore observer threw: " + e.getMessage());
}
}
@@ -1770,8 +1770,10 @@ public class BackupManagerService {
}
return; // done; don't fall through to the error case
}
- } catch (RemoteException e) {
+ } catch (Exception e) {
// transport threw when asked its name; fall through to the lookup-failed case
+ Slog.e(TAG, "Transport " + transportName + " failed to report name: "
+ + e.getMessage());
}
// The named transport doesn't exist or threw. This operation is
@@ -1859,7 +1861,7 @@ public class BackupManagerService {
System.currentTimeMillis() + delay, mRunInitIntent);
}
}
- } catch (RemoteException e) {
+ } catch (Exception e) {
// the transport threw when asked its file naming prefs; declare it invalid
Slog.e(TAG, "Unable to register transport as " + name);
mTransportNames.remove(component);
@@ -2065,8 +2067,9 @@ public class BackupManagerService {
IBackupTransport transport = IBackupTransport.Stub.asInterface(service);
registerTransport(transport.name(), name, transport);
EventLog.writeEvent(EventLogTags.BACKUP_TRANSPORT_LIFECYCLE, name, 1);
- } catch (RemoteException e) {
- Slog.e(TAG, "Unable to register transport " + component);
+ } catch (Exception e) {
+ Slog.e(TAG, "Unable to register transport " + component
+ + ": " + e.getMessage());
EventLog.writeEvent(EventLogTags.BACKUP_TRANSPORT_LIFECYCLE, name, 0);
}
}
@@ -2529,8 +2532,8 @@ public class BackupManagerService {
String dirName;
try {
dirName = transport.transportDirName();
- } catch (RemoteException e) {
- Slog.e(TAG, "Transport became unavailable while attempting backup");
+ } catch (Exception e) {
+ Slog.e(TAG, "Transport unavailable while attempting backup: " + e.getMessage());
sendBackupFinished(observer, BackupManager.ERROR_TRANSPORT_ABORTED);
return BackupManager.ERROR_TRANSPORT_ABORTED;
}
@@ -2974,9 +2977,10 @@ public class BackupManagerService {
try {
mCurrentToken = mTransport.getCurrentRestoreSet();
writeRestoreTokens();
- } catch (RemoteException e) {
+ } catch (Exception e) {
// nothing for it at this point, unfortunately, but this will be
// recorded the next time we fully succeed.
+ Slog.e(TAG, "Transport threw reporting restore set: " + e.getMessage());
addBackupTrace("transport threw returning token");
}
}
@@ -3001,7 +3005,7 @@ public class BackupManagerService {
}
}
} catch (Exception e) {
- Slog.w(TAG, "Failed to query transport name heading for init", e);
+ Slog.w(TAG, "Failed to query transport name for init: " + e.getMessage());
// swallow it and proceed; we don't rely on this
}
clearMetadata();
@@ -3367,8 +3371,8 @@ public class BackupManagerService {
try {
long quota = mTransport.getBackupQuota(mCurrentPackage.packageName, false);
mAgentBinder.doQuotaExceeded(size, quota);
- } catch (RemoteException e) {
- Slog.e(TAG, "Unable to contact backup agent for quota exceeded");
+ } catch (Exception e) {
+ Slog.e(TAG, "Unable to notify about quota exceeded: " + e.getMessage());
}
}
nextState = (mQueue.isEmpty()) ? BackupState.FINAL : BackupState.RUNNING_QUEUE;
@@ -3406,7 +3410,7 @@ public class BackupManagerService {
try {
delay = mTransport.requestBackupTime();
} catch (Exception e) {
- Slog.w(TAG, "Unable to contact transport for recommended backoff");
+ Slog.w(TAG, "Unable to contact transport for recommended backoff: " + e.getMessage());
delay = 0; // use the scheduler's default
}
KeyValueBackupJob.schedule(mContext, delay);
@@ -4324,7 +4328,10 @@ public class BackupManagerService {
Slog.e(TAG, "Internal exception during full backup", e);
} finally {
try {
- if (out != null) out.close();
+ if (out != null) {
+ out.flush();
+ out.close();
+ }
mOutputFile.close();
} catch (IOException e) {
/* nothing we can do about this */
@@ -4662,6 +4669,13 @@ public class BackupManagerService {
}
cleanUpPipes(transportPipes);
cleanUpPipes(enginePipes);
+ if (currentPackage.applicationInfo != null) {
+ Slog.i(TAG, "Unbinding agent in " + packageName);
+ addBackupTrace("unbinding " + packageName);
+ try {
+ mActivityManager.unbindBackupAgent(currentPackage.applicationInfo);
+ } catch (RemoteException e) { /* can't happen; activity manager is local */ }
+ }
}
} catch (Exception e) {
backupRunStatus = BackupManager.ERROR_TRANSPORT_ABORTED;
@@ -4997,7 +5011,7 @@ public class BackupManagerService {
return false;
}
} catch (Exception e) {
- Slog.w(TAG, "Unable to contact transport");
+ Slog.w(TAG, "Unable to get transport name: " + e.getMessage());
return false;
}
@@ -8221,9 +8235,9 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF
// Success; cache the metadata and continue as expected with the
// next state already enqueued
- } catch (RemoteException e) {
+ } catch (Exception e) {
// If we lost the transport at any time, halt
- Slog.e(TAG, "Unable to contact transport for restore");
+ Slog.e(TAG, "Unable to contact transport for restore: " + e.getMessage());
mStatus = BackupTransport.TRANSPORT_ERROR;
mBackupHandler.removeMessages(MSG_BACKUP_RESTORE_STEP, this);
executeNextState(UnifiedRestoreState.FINAL);
@@ -8320,8 +8334,9 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF
nextState = UnifiedRestoreState.RUNNING_QUEUE;
return;
}
- } catch (RemoteException e) {
- Slog.e(TAG, "Can't get next target from transport; ending restore");
+ } catch (Exception e) {
+ Slog.e(TAG, "Can't get next restore target from transport; halting: "
+ + e.getMessage());
EventLog.writeEvent(EventLogTags.RESTORE_TRANSPORT_FAILURE);
nextState = UnifiedRestoreState.FINAL;
return;
@@ -8631,11 +8646,11 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF
EventLog.writeEvent(EventLogTags.RESTORE_AGENT_FAILURE,
mCurrentPackage.packageName, "I/O error on pipes");
status = BackupTransport.AGENT_ERROR;
- } catch (RemoteException e) {
- // The transport went away; terminate the whole operation. Closing
+ } catch (Exception e) {
+ // The transport threw; terminate the whole operation. Closing
// the sockets will wake up the engine and it will then tidy up the
// remote end.
- Slog.e(TAG, "Transport failed during restore");
+ Slog.e(TAG, "Transport failed during restore: " + e.getMessage());
EventLog.writeEvent(EventLogTags.RESTORE_TRANSPORT_FAILURE);
status = BackupTransport.TRANSPORT_ERROR;
} finally {
@@ -8673,9 +8688,10 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF
// level is immaterial; we need to tell the transport to bail
try {
mTransport.abortFullRestore();
- } catch (RemoteException e) {
+ } catch (Exception e) {
// transport itself is dead; make sure we handle this as a
// fatal error
+ Slog.e(TAG, "Transport threw from abortFullRestore: " + e.getMessage());
status = BackupTransport.TRANSPORT_ERROR;
}
@@ -9023,16 +9039,15 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF
// Tell the transport to remove all the persistent storage for the app
// TODO - need to handle failures
mTransport.clearBackupData(mPackage);
- } catch (RemoteException e) {
- // can't happen; the transport is local
} catch (Exception e) {
- Slog.e(TAG, "Transport threw attempting to clear data for " + mPackage);
+ Slog.e(TAG, "Transport threw clearing data for " + mPackage + ": " + e.getMessage());
} finally {
try {
// TODO - need to handle failures
mTransport.finishBackup();
- } catch (RemoteException e) {
- // can't happen; the transport is local
+ } catch (Exception e) {
+ // Nothing we can do here, alas
+ Slog.e(TAG, "Unable to mark clear operation finished: " + e.getMessage());
}
// Last but not least, release the cpu
@@ -9091,8 +9106,6 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF
System.currentTimeMillis() + delay, mRunInitIntent);
}
}
- } catch (RemoteException e) {
- // can't happen; the transports are local
} catch (Exception e) {
Slog.e(TAG, "Unexpected error performing init", e);
} finally {
@@ -9780,8 +9793,9 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF
if (MORE_DEBUG) Slog.d(TAG, "getConfigurationIntent() returning config intent "
+ intent);
return intent;
- } catch (RemoteException e) {
+ } catch (Exception e) {
/* fall through to return null */
+ Slog.e(TAG, "Unable to get configuration intent from transport: " + e.getMessage());
}
}
}
@@ -9805,8 +9819,9 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF
final String text = transport.currentDestinationString();
if (MORE_DEBUG) Slog.d(TAG, "getDestinationString() returning " + text);
return text;
- } catch (RemoteException e) {
+ } catch (Exception e) {
/* fall through to return null */
+ Slog.e(TAG, "Unable to get string from transport: " + e.getMessage());
}
}
}
@@ -9827,8 +9842,9 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF
if (MORE_DEBUG) Slog.d(TAG, "getDataManagementIntent() returning intent "
+ intent);
return intent;
- } catch (RemoteException e) {
+ } catch (Exception e) {
/* fall through to return null */
+ Slog.e(TAG, "Unable to get management intent from transport: " + e.getMessage());
}
}
}
@@ -9849,8 +9865,9 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF
final String text = transport.dataManagementLabel();
if (MORE_DEBUG) Slog.d(TAG, "getDataManagementLabel() returning " + text);
return text;
- } catch (RemoteException e) {
+ } catch (Exception e) {
/* fall through to return null */
+ Slog.e(TAG, "Unable to get management label from transport: " + e.getMessage());
}
}
}
@@ -9943,9 +9960,9 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF
msg.obj = new RestoreParams(transport, dirName, null,
restoreSet, packageName, token);
mBackupHandler.sendMessage(msg);
- } catch (RemoteException e) {
- // Binding to the transport broke; back off and proceed with the installation.
- Slog.e(TAG, "Unable to contact transport");
+ } catch (Exception e) {
+ // Calling into the transport broke; back off and proceed with the installation.
+ Slog.e(TAG, "Unable to contact transport: " + e.getMessage());
skip = true;
}
}
@@ -10066,8 +10083,8 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF
try {
return transport.isAppEligibleForBackup(packageInfo,
appGetsFullBackup(packageInfo));
- } catch (RemoteException e) {
- Slog.e(TAG, "Unable to contact transport");
+ } catch (Exception e) {
+ Slog.e(TAG, "Unable to ask about eligibility: " + e.getMessage());
}
}
// If transport is not present we couldn't tell that the package is not eligible.
@@ -10169,9 +10186,9 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF
String dirName;
try {
dirName = mRestoreTransport.transportDirName();
- } catch (RemoteException e) {
+ } catch (Exception e) {
// Transport went AWOL; fail.
- Slog.e(TAG, "Unable to contact transport for restore");
+ Slog.e(TAG, "Unable to get transport dir for restore: " + e.getMessage());
return -1;
}
@@ -10251,9 +10268,9 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF
String dirName;
try {
dirName = mRestoreTransport.transportDirName();
- } catch (RemoteException e) {
+ } catch (Exception e) {
// Transport went AWOL; fail.
- Slog.e(TAG, "Unable to contact transport for restore");
+ Slog.e(TAG, "Unable to get transport name for restoreSome: " + e.getMessage());
return -1;
}
@@ -10341,9 +10358,9 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF
String dirName;
try {
dirName = mRestoreTransport.transportDirName();
- } catch (RemoteException e) {
+ } catch (Exception e) {
// Transport went AWOL; fail.
- Slog.e(TAG, "Unable to contact transport for restore");
+ Slog.e(TAG, "Unable to get transport dir for restorePackage: " + e.getMessage());
return -1;
}
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java
index 312553a980b2..4dd88b20fb7f 100644
--- a/services/core/java/com/android/server/AlarmManagerService.java
+++ b/services/core/java/com/android/server/AlarmManagerService.java
@@ -2547,7 +2547,9 @@ class AlarmManagerService extends SystemService {
} else {
// Just in case -- even though no wakeup flag was set, make sure
// we have updated the kernel to the next alarm time.
- rescheduleKernelAlarmsLocked();
+ synchronized (mLock) {
+ rescheduleKernelAlarmsLocked();
+ }
}
}
}
diff --git a/services/core/java/com/android/server/AnyMotionDetector.java b/services/core/java/com/android/server/AnyMotionDetector.java
index a8ae914d0e9a..f93c716ae162 100644
--- a/services/core/java/com/android/server/AnyMotionDetector.java
+++ b/services/core/java/com/android/server/AnyMotionDetector.java
@@ -70,6 +70,9 @@ public class AnyMotionDetector {
/** The interval between accelerometer orientation measurements. */
private static final long ORIENTATION_MEASUREMENT_INTERVAL_MILLIS = 5000;
+ /** The maximum duration we will hold a wakelock to determine stationary status. */
+ private static final long WAKELOCK_TIMEOUT_MILLIS = 30000;
+
/**
* The duration in milliseconds after which an orientation measurement is considered
* too stale to be used.
@@ -141,25 +144,30 @@ public class AnyMotionDetector {
mCurrentGravityVector = null;
mPreviousGravityVector = null;
mWakeLock.acquire();
+ Message wakelockTimeoutMsg = Message.obtain(mHandler, mWakelockTimeout);
+ mHandler.sendMessageDelayed(wakelockTimeoutMsg, WAKELOCK_TIMEOUT_MILLIS);
startOrientationMeasurementLocked();
}
}
}
public void stop() {
- if (mState == STATE_ACTIVE) {
- synchronized (mLock) {
+ synchronized (mLock) {
+ if (mState == STATE_ACTIVE) {
mState = STATE_INACTIVE;
if (DEBUG) Slog.d(TAG, "Moved from STATE_ACTIVE to STATE_INACTIVE.");
- if (mMeasurementInProgress) {
- mMeasurementInProgress = false;
- mSensorManager.unregisterListener(mListener);
- }
- mHandler.removeCallbacks(mMeasurementTimeout);
- mHandler.removeCallbacks(mSensorRestart);
- mCurrentGravityVector = null;
- mPreviousGravityVector = null;
+ }
+ if (mMeasurementInProgress) {
+ mMeasurementInProgress = false;
+ mSensorManager.unregisterListener(mListener);
+ }
+ mHandler.removeCallbacks(mMeasurementTimeout);
+ mHandler.removeCallbacks(mSensorRestart);
+ mCurrentGravityVector = null;
+ mPreviousGravityVector = null;
+ if (mWakeLock.isHeld()) {
mWakeLock.release();
+ mHandler.removeCallbacks(mWakelockTimeout);
}
}
}
@@ -173,9 +181,8 @@ public class AnyMotionDetector {
mMeasurementInProgress = true;
mRunningStats.reset();
}
- Message msg = Message.obtain(mHandler, mMeasurementTimeout);
- msg.setAsynchronous(true);
- mHandler.sendMessageDelayed(msg, ACCELEROMETER_DATA_TIMEOUT_MILLIS);
+ Message measurementTimeoutMsg = Message.obtain(mHandler, mMeasurementTimeout);
+ mHandler.sendMessageDelayed(measurementTimeoutMsg, ACCELEROMETER_DATA_TIMEOUT_MILLIS);
}
}
@@ -186,10 +193,12 @@ public class AnyMotionDetector {
if (mMeasurementInProgress) {
mSensorManager.unregisterListener(mListener);
mHandler.removeCallbacks(mMeasurementTimeout);
- long detectionEndTime = SystemClock.elapsedRealtime();
mMeasurementInProgress = false;
mPreviousGravityVector = mCurrentGravityVector;
mCurrentGravityVector = mRunningStats.getRunningAverage();
+ if (mRunningStats.getSampleCount() == 0) {
+ Slog.w(TAG, "No accelerometer data acquired for orientation measurement.");
+ }
if (DEBUG) {
Slog.d(TAG, "mRunningStats = " + mRunningStats.toString());
String currentGravityVectorString = (mCurrentGravityVector == null) ?
@@ -203,7 +212,10 @@ public class AnyMotionDetector {
status = getStationaryStatus();
if (DEBUG) Slog.d(TAG, "getStationaryStatus() returned " + status);
if (status != RESULT_UNKNOWN) {
- mWakeLock.release();
+ if (mWakeLock.isHeld()) {
+ mWakeLock.release();
+ mHandler.removeCallbacks(mWakelockTimeout);
+ }
if (DEBUG) {
Slog.d(TAG, "Moved from STATE_ACTIVE to STATE_INACTIVE. status = " + status);
}
@@ -217,7 +229,6 @@ public class AnyMotionDetector {
" scheduled in " + ORIENTATION_MEASUREMENT_INTERVAL_MILLIS +
" milliseconds.");
Message msg = Message.obtain(mHandler, mSensorRestart);
- msg.setAsynchronous(true);
mHandler.sendMessageDelayed(msg, ORIENTATION_MEASUREMENT_INTERVAL_MILLIS);
}
}
@@ -271,6 +282,7 @@ public class AnyMotionDetector {
}
}
if (status != RESULT_UNKNOWN) {
+ mHandler.removeCallbacks(mWakelockTimeout);
mCallback.onAnyMotionResult(status);
}
}
@@ -290,20 +302,30 @@ public class AnyMotionDetector {
};
private final Runnable mMeasurementTimeout = new Runnable() {
- @Override
- public void run() {
- int status = RESULT_UNKNOWN;
- synchronized (mLock) {
- if (DEBUG) Slog.i(TAG, "mMeasurementTimeout. Failed to collect sufficient accel " +
+ @Override
+ public void run() {
+ int status = RESULT_UNKNOWN;
+ synchronized (mLock) {
+ if (DEBUG) Slog.i(TAG, "mMeasurementTimeout. Failed to collect sufficient accel " +
"data within " + ACCELEROMETER_DATA_TIMEOUT_MILLIS + " ms. Stopping " +
"orientation measurement.");
- status = stopOrientationMeasurementLocked();
- }
- if (status != RESULT_UNKNOWN) {
- mCallback.onAnyMotionResult(status);
- }
- }
- };
+ status = stopOrientationMeasurementLocked();
+ }
+ if (status != RESULT_UNKNOWN) {
+ mHandler.removeCallbacks(mWakelockTimeout);
+ mCallback.onAnyMotionResult(status);
+ }
+ }
+ };
+
+ private final Runnable mWakelockTimeout = new Runnable() {
+ @Override
+ public void run() {
+ synchronized (mLock) {
+ stop();
+ }
+ }
+ };
/**
* A timestamped three dimensional vector and some vector operations.
diff --git a/services/core/java/com/android/server/DeviceIdleController.java b/services/core/java/com/android/server/DeviceIdleController.java
index afed5ef066ff..488f0e793c9a 100644
--- a/services/core/java/com/android/server/DeviceIdleController.java
+++ b/services/core/java/com/android/server/DeviceIdleController.java
@@ -973,13 +973,12 @@ public class DeviceIdleController extends SystemService
cancelSensingTimeoutAlarmLocked();
}
}
- if (result == AnyMotionDetector.RESULT_MOVED) {
- if (DEBUG) Slog.d(TAG, "RESULT_MOVED received.");
+ if ((result == AnyMotionDetector.RESULT_MOVED) ||
+ (result == AnyMotionDetector.RESULT_UNKNOWN)) {
synchronized (this) {
- handleMotionDetectedLocked(mConstants.INACTIVE_TIMEOUT, "sense_motion");
+ handleMotionDetectedLocked(mConstants.INACTIVE_TIMEOUT, "non_stationary");
}
} else if (result == AnyMotionDetector.RESULT_STATIONARY) {
- if (DEBUG) Slog.d(TAG, "RESULT_STATIONARY received.");
if (mState == STATE_SENSING) {
// If we are currently sensing, it is time to move to locating.
synchronized (this) {
diff --git a/services/core/java/com/android/server/PersistentDataBlockService.java b/services/core/java/com/android/server/PersistentDataBlockService.java
index e233b1c84bc6..080b46c24a2f 100644
--- a/services/core/java/com/android/server/PersistentDataBlockService.java
+++ b/services/core/java/com/android/server/PersistentDataBlockService.java
@@ -157,11 +157,10 @@ public class PersistentDataBlockService extends SystemService {
}
}
- private void enforceFactoryResetAllowed() {
- final boolean isOemUnlockRestricted = UserManager.get(mContext)
- .hasUserRestriction(UserManager.DISALLOW_FACTORY_RESET);
- if (isOemUnlockRestricted) {
- throw new SecurityException("OEM unlock is disallowed by DISALLOW_FACTORY_RESET");
+ private void enforceUserRestriction(String userRestriction) {
+ if (UserManager.get(mContext).hasUserRestriction(userRestriction)) {
+ throw new SecurityException(
+ "OEM unlock is disallowed by user restriction: " + userRestriction);
}
}
@@ -467,13 +466,9 @@ public class PersistentDataBlockService extends SystemService {
enforceIsAdmin();
if (enabled) {
- // Do not allow oem unlock to be enabled if it has been disallowed.
- if (Settings.Global.getInt(getContext().getContentResolver(),
- Settings.Global.OEM_UNLOCK_DISALLOWED, 0) == 1) {
- throw new SecurityException(
- "OEM unlock has been disallowed by OEM_UNLOCK_DISALLOWED.");
- }
- enforceFactoryResetAllowed();
+ // Do not allow oem unlock to be enabled if it's disallowed by a user restriction.
+ enforceUserRestriction(UserManager.DISALLOW_OEM_UNLOCK);
+ enforceUserRestriction(UserManager.DISALLOW_FACTORY_RESET);
}
synchronized (mLock) {
doSetOemUnlockEnabledLocked(enabled);
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index cac1f4170ac9..1f0dbfe361f7 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -12042,6 +12042,9 @@ public final class ActivityManagerService extends ActivityManagerNative
case ActivityManager.BUGREPORT_OPTION_REMOTE:
service = "bugreportremote";
break;
+ case ActivityManager.BUGREPORT_OPTION_WEAR:
+ service = "bugreportwear";
+ break;
}
if (service == null) {
throw new IllegalArgumentException("Provided bugreport type is not correct, value: "
@@ -18669,7 +18672,7 @@ public final class ActivityManagerService extends ActivityManagerNative
synchronized(this) {
final long origId = Binder.clearCallingIdentity();
- updateConfigurationLocked(values, null, false, true, userId);
+ updateConfigurationLocked(values, null, false, true, userId, false /* deferResume */);
Binder.restoreCallingIdentity(origId);
}
}
@@ -18737,11 +18740,16 @@ public final class ActivityManagerService extends ActivityManagerNative
updateConfigurationLocked(configuration, null, false);
}
- boolean updateConfigurationLocked(Configuration values,
- ActivityRecord starting, boolean initLocale) {
+ boolean updateConfigurationLocked(Configuration values, ActivityRecord starting,
+ boolean initLocale) {
+ return updateConfigurationLocked(values, starting, initLocale, false /* deferResume */);
+ }
+
+ boolean updateConfigurationLocked(Configuration values, ActivityRecord starting,
+ boolean initLocale, boolean deferResume) {
// pass UserHandle.USER_NULL as userId because we don't persist configuration for any user
- return updateConfigurationLocked(values, starting, initLocale, false,
- UserHandle.USER_NULL);
+ return updateConfigurationLocked(values, starting, initLocale, false /* persistent */,
+ UserHandle.USER_NULL, deferResume);
}
// To cache the list of supported system locales
@@ -18757,8 +18765,8 @@ public final class ActivityManagerService extends ActivityManagerNative
* @param userId is only used when persistent parameter is set to true to persist configuration
* for that particular user
*/
- private boolean updateConfigurationLocked(Configuration values,
- ActivityRecord starting, boolean initLocale, boolean persistent, int userId) {
+ private boolean updateConfigurationLocked(Configuration values, ActivityRecord starting,
+ boolean initLocale, boolean persistent, int userId, boolean deferResume) {
int changes = 0;
if (mWindowManager != null) {
@@ -18886,7 +18894,7 @@ public final class ActivityManagerService extends ActivityManagerNative
for (int stackId : resizedStacks) {
final Rect newBounds = mWindowManager.getBoundsForNewConfiguration(stackId);
mStackSupervisor.resizeStackLocked(
- stackId, newBounds, null, null, false, false, !DEFER_RESUME);
+ stackId, newBounds, null, null, false, false, deferResume);
}
}
}
@@ -21783,7 +21791,8 @@ public final class ActivityManagerService extends ActivityManagerNative
Preconditions.checkNotNull(values, "Configuration must not be null");
Preconditions.checkArgumentNonnegative(userId, "userId " + userId + " not supported");
synchronized (ActivityManagerService.this) {
- updateConfigurationLocked(values, null, false, true, userId);
+ updateConfigurationLocked(values, null, false, true, userId,
+ false /* deferResume */);
}
}
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index a10266483834..eb02dc34e1a2 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -2051,6 +2051,14 @@ final class ActivityStack {
// We don't want to clear starting window for activities that aren't behind fullscreen
// activities as we need to display their starting window until they are done initializing.
boolean behindFullscreenActivity = false;
+
+ if (getStackVisibilityLocked(null) == STACK_INVISIBLE) {
+ // The stack is not visible, so no activity in it should be displaying a starting
+ // window. Mark all activities below top and behind fullscreen.
+ aboveTop = false;
+ behindFullscreenActivity = true;
+ }
+
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) {
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 82668e45812f..a4fc251b70d8 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -1189,7 +1189,10 @@ public final class ActivityStackSupervisor implements DisplayListener {
Configuration config = mWindowManager.updateOrientationFromAppTokens(
mService.mConfiguration,
r.mayFreezeScreenLocked(app) ? r.appToken : null);
- mService.updateConfigurationLocked(config, r, false);
+ // Deferring resume here because we're going to launch new activity shortly.
+ // We don't want to perform a redundant launch of the same record while ensuring
+ // configurations and trying to resume top activity of focused stack.
+ mService.updateConfigurationLocked(config, r, false, true /* deferResume */);
}
r.app = app;
@@ -2004,7 +2007,7 @@ public final class ActivityStackSupervisor implements DisplayListener {
boolean preserveWindows, boolean allowResizeInDockedMode, boolean deferResume) {
if (stackId == DOCKED_STACK_ID) {
resizeDockedStackLocked(bounds, tempTaskBounds, tempTaskInsetBounds, null, null,
- preserveWindows);
+ preserveWindows, deferResume);
return;
}
final ActivityStack stack = getStack(stackId);
@@ -2154,8 +2157,16 @@ public final class ActivityStackSupervisor implements DisplayListener {
}
void resizeDockedStackLocked(Rect dockedBounds, Rect tempDockedTaskBounds,
- Rect tempDockedTaskInsetBounds,
- Rect tempOtherTaskBounds, Rect tempOtherTaskInsetBounds, boolean preserveWindows) {
+ Rect tempDockedTaskInsetBounds, Rect tempOtherTaskBounds, Rect tempOtherTaskInsetBounds,
+ boolean preserveWindows) {
+ resizeDockedStackLocked(dockedBounds, tempDockedTaskBounds, tempDockedTaskInsetBounds,
+ tempOtherTaskBounds, tempOtherTaskInsetBounds, preserveWindows,
+ false /* deferResume */);
+ }
+
+ void resizeDockedStackLocked(Rect dockedBounds, Rect tempDockedTaskBounds,
+ Rect tempDockedTaskInsetBounds, Rect tempOtherTaskBounds, Rect tempOtherTaskInsetBounds,
+ boolean preserveWindows, boolean deferResume) {
if (!mAllowDockedStackResize) {
// Docked stack resize currently disabled.
@@ -2198,11 +2209,13 @@ public final class ActivityStackSupervisor implements DisplayListener {
if (StackId.isResizeableByDockedStack(i) && getStack(i) != null) {
resizeStackLocked(i, tempRect, tempOtherTaskBounds,
tempOtherTaskInsetBounds, preserveWindows,
- true /* allowResizeInDockedMode */, !DEFER_RESUME);
+ true /* allowResizeInDockedMode */, deferResume);
}
}
}
- stack.ensureVisibleActivitiesConfigurationLocked(r, preserveWindows);
+ if (!deferResume) {
+ stack.ensureVisibleActivitiesConfigurationLocked(r, preserveWindows);
+ }
} finally {
mAllowDockedStackResize = true;
mWindowManager.continueSurfaceLayout();
diff --git a/services/core/java/com/android/server/am/AppErrors.java b/services/core/java/com/android/server/am/AppErrors.java
index 49106f42044e..5807502ef791 100644
--- a/services/core/java/com/android/server/am/AppErrors.java
+++ b/services/core/java/com/android/server/am/AppErrors.java
@@ -58,6 +58,7 @@ import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
+import java.util.Set;
import java.util.concurrent.Semaphore;
import static com.android.server.Watchdog.NATIVE_STACKS_OF_INTEREST;
@@ -386,8 +387,8 @@ class AppErrors {
} catch (IllegalArgumentException e) {
// Hmm, that didn't work, app might have crashed before creating a
// recents entry. Let's see if we have a safe-to-restart intent.
- if (task.intent.getCategories().contains(
- Intent.CATEGORY_LAUNCHER)) {
+ final Set<String> cats = task.intent.getCategories();
+ if (cats != null && cats.contains(Intent.CATEGORY_LAUNCHER)) {
mService.startActivityInPackage(task.mCallingUid,
task.mCallingPackage, task.intent,
null, null, null, 0, 0,
@@ -742,6 +743,12 @@ class AppErrors {
mService.updateCpuStatsNow();
}
+ // Unless configured otherwise, swallow ANRs in background processes & kill the process.
+ boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
+ Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
+
+ boolean isSilentANR;
+
synchronized (mService) {
// PowerManager.reboot() can block for a long time, so ignore ANRs while shutting down.
if (mService.mShuttingDown) {
@@ -766,25 +773,29 @@ class AppErrors {
// Dump thread traces as quickly as we can, starting with "interesting" processes.
firstPids.add(app.pid);
- int parentPid = app.pid;
- if (parent != null && parent.app != null && parent.app.pid > 0) {
- parentPid = parent.app.pid;
- }
- if (parentPid != app.pid) firstPids.add(parentPid);
-
- if (MY_PID != app.pid && MY_PID != parentPid) firstPids.add(MY_PID);
-
- for (int i = mService.mLruProcesses.size() - 1; i >= 0; i--) {
- ProcessRecord r = mService.mLruProcesses.get(i);
- if (r != null && r.thread != null) {
- int pid = r.pid;
- if (pid > 0 && pid != app.pid && pid != parentPid && pid != MY_PID) {
- if (r.persistent) {
- firstPids.add(pid);
- if (DEBUG_ANR) Slog.i(TAG, "Adding persistent proc: " + r);
- } else {
- lastPids.put(pid, Boolean.TRUE);
- if (DEBUG_ANR) Slog.i(TAG, "Adding ANR proc: " + r);
+ // Don't dump other PIDs if it's a background ANR
+ isSilentANR = !showBackground && !app.isInterestingToUserLocked() && app.pid != MY_PID;
+ if (!isSilentANR) {
+ int parentPid = app.pid;
+ if (parent != null && parent.app != null && parent.app.pid > 0) {
+ parentPid = parent.app.pid;
+ }
+ if (parentPid != app.pid) firstPids.add(parentPid);
+
+ if (MY_PID != app.pid && MY_PID != parentPid) firstPids.add(MY_PID);
+
+ for (int i = mService.mLruProcesses.size() - 1; i >= 0; i--) {
+ ProcessRecord r = mService.mLruProcesses.get(i);
+ if (r != null && r.thread != null) {
+ int pid = r.pid;
+ if (pid > 0 && pid != app.pid && pid != parentPid && pid != MY_PID) {
+ if (r.persistent) {
+ firstPids.add(pid);
+ if (DEBUG_ANR) Slog.i(TAG, "Adding persistent proc: " + r);
+ } else {
+ lastPids.put(pid, Boolean.TRUE);
+ if (DEBUG_ANR) Slog.i(TAG, "Adding ANR proc: " + r);
+ }
}
}
}
@@ -807,10 +818,18 @@ class AppErrors {
info.append("Parent: ").append(parent.shortComponentName).append("\n");
}
- final ProcessCpuTracker processCpuTracker = new ProcessCpuTracker(true);
+ ProcessCpuTracker processCpuTracker = new ProcessCpuTracker(true);
- File tracesFile = mService.dumpStackTraces(true, firstPids, processCpuTracker, lastPids,
- NATIVE_STACKS_OF_INTEREST);
+ String[] nativeProcs = NATIVE_STACKS_OF_INTEREST;
+ // don't dump native PIDs for background ANRs
+ File tracesFile = null;
+ if (isSilentANR) {
+ tracesFile = mService.dumpStackTraces(true, firstPids, null, lastPids,
+ null);
+ } else {
+ tracesFile = mService.dumpStackTraces(true, firstPids, processCpuTracker, lastPids,
+ nativeProcs);
+ }
String cpuInfo = null;
if (ActivityManagerService.MONITOR_CPU_USAGE) {
@@ -854,14 +873,10 @@ class AppErrors {
}
}
- // Unless configured otherwise, swallow ANRs in background processes & kill the process.
- boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
- Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
-
synchronized (mService) {
mService.mBatteryStatsService.noteProcessAnr(app.processName, app.uid);
- if (!showBackground && !app.isInterestingToUserLocked() && app.pid != MY_PID) {
+ if (isSilentANR) {
app.kill("bg anr", true);
return;
}
diff --git a/services/core/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java
index 6f67b6fae8fc..92b55db40cd8 100644
--- a/services/core/java/com/android/server/connectivity/Tethering.java
+++ b/services/core/java/com/android/server/connectivity/Tethering.java
@@ -69,6 +69,7 @@ import com.android.internal.util.State;
import com.android.internal.util.StateMachine;
import com.android.server.IoThread;
import com.android.server.connectivity.tethering.IControlsTethering;
+import com.android.server.connectivity.tethering.IPv6TetheringCoordinator;
import com.android.server.connectivity.tethering.TetherInterfaceStateMachine;
import com.android.server.net.BaseNetworkObserver;
@@ -1143,7 +1144,8 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
// Because we excise interfaces immediately from mTetherStates, we must maintain mNotifyList
// so that the garbage collector does not clean up the state machine before it has a chance
// to tear itself down.
- private ArrayList<TetherInterfaceStateMachine> mNotifyList;
+ private final ArrayList<TetherInterfaceStateMachine> mNotifyList;
+ private final IPv6TetheringCoordinator mIPv6TetheringCoordinator;
private int mMobileApnReserved = ConnectivityManager.TYPE_NONE;
private NetworkCallback mMobileUpstreamCallback;
@@ -1171,6 +1173,7 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
addState(mSetDnsForwardersErrorState);
mNotifyList = new ArrayList<>();
+ mIPv6TetheringCoordinator = new IPv6TetheringCoordinator(mNotifyList);
setInitialState(mInitialState);
}
diff --git a/services/core/java/com/android/server/connectivity/tethering/IPv6TetheringCoordinator.java b/services/core/java/com/android/server/connectivity/tethering/IPv6TetheringCoordinator.java
new file mode 100644
index 000000000000..825439786360
--- /dev/null
+++ b/services/core/java/com/android/server/connectivity/tethering/IPv6TetheringCoordinator.java
@@ -0,0 +1,253 @@
+/*
+ * 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.server.connectivity.tethering;
+
+import android.net.ConnectivityManager;
+import android.net.IpPrefix;
+import android.net.LinkAddress;
+import android.net.LinkProperties;
+import android.net.Network;
+import android.net.NetworkCapabilities;
+import android.net.NetworkState;
+import android.net.RouteInfo;
+import android.util.Log;
+
+import java.net.Inet6Address;
+import java.net.InetAddress;
+import java.util.ArrayList;
+
+
+/**
+ * IPv6 tethering is rather different from IPv4 owing to the absence of NAT.
+ * This coordinator is responsible for evaluating the dedicated prefixes
+ * assigned to the device and deciding how to divvy them up among downstream
+ * interfaces.
+ *
+ * @hide
+ */
+public class IPv6TetheringCoordinator {
+ private static final String TAG = IPv6TetheringCoordinator.class.getSimpleName();
+ private static final boolean DBG = false;
+ private static final boolean VDBG = false;
+
+ private final ArrayList<TetherInterfaceStateMachine> mNotifyList;
+ private NetworkState mUpstreamNetworkState;
+
+ public IPv6TetheringCoordinator(ArrayList<TetherInterfaceStateMachine> notifyList) {
+ mNotifyList = notifyList;
+ }
+
+ public void updateUpstreamNetworkState(NetworkState ns) {
+ if (VDBG) {
+ Log.d(TAG, "updateUpstreamNetworkState: " + toDebugString(ns));
+ }
+ if (ns == null || ns.network == null) {
+ stopIPv6TetheringOnAllInterfaces();
+ setUpstreamNetworkState(null);
+ return;
+ }
+
+ if (mUpstreamNetworkState != null &&
+ !ns.network.equals(mUpstreamNetworkState.network)) {
+ stopIPv6TetheringOnAllInterfaces();
+ }
+ setUpstreamNetworkState(ns);
+ maybeUpdateIPv6TetheringInterfaces();
+ }
+
+ private void stopIPv6TetheringOnAllInterfaces() {
+ for (TetherInterfaceStateMachine sm : mNotifyList) {
+ sm.sendMessage(TetherInterfaceStateMachine.CMD_IPV6_TETHER_UPDATE,
+ 0, 0, null);
+ }
+ }
+
+ private void setUpstreamNetworkState(NetworkState ns) {
+ if (!canTetherIPv6(ns)) {
+ mUpstreamNetworkState = null;
+ } else {
+ mUpstreamNetworkState = new NetworkState(
+ null,
+ new LinkProperties(ns.linkProperties),
+ new NetworkCapabilities(ns.networkCapabilities),
+ new Network(ns.network),
+ null,
+ null);
+ }
+
+ if (DBG) {
+ Log.d(TAG, "setUpstreamNetworkState: " + toDebugString(mUpstreamNetworkState));
+ }
+ }
+
+ private void maybeUpdateIPv6TetheringInterfaces() {
+ if (mUpstreamNetworkState == null) return;
+
+ for (TetherInterfaceStateMachine sm : mNotifyList) {
+ final LinkProperties lp = getInterfaceIPv6LinkProperties(sm.interfaceType());
+ if (lp != null) {
+ sm.sendMessage(TetherInterfaceStateMachine.CMD_IPV6_TETHER_UPDATE, 0, 0, lp);
+ }
+ break;
+ }
+ }
+
+ private LinkProperties getInterfaceIPv6LinkProperties(int interfaceType) {
+ // NOTE: Here, in future, we would have policies to decide how to divvy
+ // up the available dedicated prefixes among downstream interfaces.
+ // At this time we have no such mechanism--we only support tethering
+ // IPv6 toward Wi-Fi interfaces.
+
+ switch (interfaceType) {
+ case ConnectivityManager.TETHERING_WIFI:
+ final LinkProperties lp = getIPv6OnlyLinkProperties(
+ mUpstreamNetworkState.linkProperties);
+ if (lp.hasIPv6DefaultRoute() && lp.hasGlobalIPv6Address()) {
+ return lp;
+ }
+ break;
+ }
+
+ return null;
+ }
+
+ private static boolean canTetherIPv6(NetworkState ns) {
+ // Broadly speaking:
+ //
+ // [1] does the upstream have an IPv6 default route?
+ //
+ // and
+ //
+ // [2] does the upstream have one or more global IPv6 /64s
+ // dedicated to this device?
+ //
+ // In lieu of Prefix Delegation and other evaluation of whether a
+ // prefix may or may not be dedicated to this device, for now just
+ // check whether the upstream is TRANSPORT_CELLULAR. This works
+ // because "[t]he 3GPP network allocates each default bearer a unique
+ // /64 prefix", per RFC 6459, Section 5.2.
+
+ final boolean canTether =
+ (ns != null) && (ns.network != null) &&
+ (ns.linkProperties != null) && (ns.networkCapabilities != null) &&
+ // At least one upstream DNS server:
+ ns.linkProperties.isProvisioned() &&
+ // Minimal amount of IPv6 provisioning:
+ ns.linkProperties.hasIPv6DefaultRoute() &&
+ ns.linkProperties.hasGlobalIPv6Address() &&
+ // Temporary approximation of "dedicated prefix":
+ ns.networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR);
+
+ // For now, we do not support separate IPv4 and IPv6 upstreams (e.g.
+ // tethering with 464xlat involved). TODO: Rectify this shortcoming,
+ // likely by calling NetworkManagementService#startInterfaceForwarding()
+ // for all upstream interfaces.
+ RouteInfo v4default = null;
+ RouteInfo v6default = null;
+ if (canTether) {
+ for (RouteInfo r : ns.linkProperties.getAllRoutes()) {
+ if (r.isIPv4Default()) {
+ v4default = r;
+ } else if (r.isIPv6Default()) {
+ v6default = r;
+ }
+
+ if (v4default != null && v6default != null) {
+ break;
+ }
+ }
+ }
+
+ final boolean supportedConfiguration =
+ (v4default != null) && (v6default != null) &&
+ (v4default.getInterface() != null) &&
+ v4default.getInterface().equals(v6default.getInterface());
+
+ final boolean outcome = canTether && supportedConfiguration;
+
+ if (VDBG) {
+ if (ns == null) {
+ Log.d(TAG, "No available upstream.");
+ } else {
+ Log.d(TAG, String.format("IPv6 tethering is %s for upstream: %s",
+ (outcome ? "available" : "not available"), toDebugString(ns)));
+ }
+ }
+
+ return outcome;
+ }
+
+ private static LinkProperties getIPv6OnlyLinkProperties(LinkProperties lp) {
+ final LinkProperties v6only = new LinkProperties();
+ if (lp == null) {
+ return v6only;
+ }
+
+ // NOTE: At this time we don't copy over any information about any
+ // stacked links. No current stacked link configuration has IPv6.
+
+ v6only.setInterfaceName(lp.getInterfaceName());
+
+ v6only.setMtu(lp.getMtu());
+
+ for (LinkAddress linkAddr : lp.getLinkAddresses()) {
+ if (linkAddr.isGlobalPreferred() && linkAddr.getPrefixLength() == 64) {
+ v6only.addLinkAddress(linkAddr);
+ }
+ }
+
+ for (RouteInfo routeInfo : lp.getRoutes()) {
+ final IpPrefix destination = routeInfo.getDestination();
+ if ((destination.getAddress() instanceof Inet6Address) &&
+ (destination.getPrefixLength() <= 64)) {
+ v6only.addRoute(routeInfo);
+ }
+ }
+
+ for (InetAddress dnsServer : lp.getDnsServers()) {
+ if (isIPv6GlobalAddress(dnsServer)) {
+ // For now we include ULAs.
+ v6only.addDnsServer(dnsServer);
+ }
+ }
+
+ v6only.setDomains(lp.getDomains());
+
+ return v6only;
+ }
+
+ // TODO: Delete this and switch to LinkAddress#isGlobalPreferred once we
+ // announce our own IPv6 address as DNS server.
+ private static boolean isIPv6GlobalAddress(InetAddress ip) {
+ return (ip instanceof Inet6Address) &&
+ !ip.isAnyLocalAddress() &&
+ !ip.isLoopbackAddress() &&
+ !ip.isLinkLocalAddress() &&
+ !ip.isSiteLocalAddress() &&
+ !ip.isMulticastAddress();
+ }
+
+ private static String toDebugString(NetworkState ns) {
+ if (ns == null) {
+ return "NetworkState{null}";
+ }
+ return String.format("NetworkState{%s, %s, %s}",
+ ns.network,
+ ns.networkCapabilities,
+ ns.linkProperties);
+ }
+}
diff --git a/services/core/java/com/android/server/connectivity/tethering/IPv6TetheringInterfaceServices.java b/services/core/java/com/android/server/connectivity/tethering/IPv6TetheringInterfaceServices.java
new file mode 100644
index 000000000000..b74283853726
--- /dev/null
+++ b/services/core/java/com/android/server/connectivity/tethering/IPv6TetheringInterfaceServices.java
@@ -0,0 +1,177 @@
+/*
+ * 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.server.connectivity.tethering;
+
+import android.net.IpPrefix;
+import android.net.LinkAddress;
+import android.net.LinkProperties;
+import android.net.NetworkCapabilities;
+import android.net.NetworkState;
+import android.net.RouteInfo;
+import android.net.ip.RouterAdvertisementDaemon;
+import android.net.ip.RouterAdvertisementDaemon.RaParams;
+import android.os.INetworkManagementService;
+import android.os.RemoteException;
+import android.util.Log;
+
+import java.net.Inet6Address;
+import java.net.InetAddress;
+import java.net.NetworkInterface;
+import java.net.SocketException;
+import java.util.ArrayList;
+import java.util.HashSet;
+
+
+/**
+ * @hide
+ */
+class IPv6TetheringInterfaceServices {
+ private static final String TAG = IPv6TetheringInterfaceServices.class.getSimpleName();
+
+ private final String mIfName;
+ private final INetworkManagementService mNMService;
+
+ private NetworkInterface mNetworkInterface;
+ private byte[] mHwAddr;
+ private ArrayList<RouteInfo> mLastLocalRoutes;
+ private RouterAdvertisementDaemon mRaDaemon;
+ private RaParams mLastRaParams;
+
+ IPv6TetheringInterfaceServices(String ifname, INetworkManagementService nms) {
+ mIfName = ifname;
+ mNMService = nms;
+ }
+
+ public boolean start() {
+ try {
+ mNetworkInterface = NetworkInterface.getByName(mIfName);
+ } catch (SocketException e) {
+ Log.e(TAG, "Failed to find NetworkInterface for " + mIfName, e);
+ stop();
+ return false;
+ }
+
+ try {
+ mHwAddr = mNetworkInterface.getHardwareAddress();
+ } catch (SocketException e) {
+ Log.e(TAG, "Failed to find hardware address for " + mIfName, e);
+ stop();
+ return false;
+ }
+
+ final int ifindex = mNetworkInterface.getIndex();
+ mRaDaemon = new RouterAdvertisementDaemon(mIfName, ifindex, mHwAddr);
+ if (!mRaDaemon.start()) {
+ stop();
+ return false;
+ }
+
+ return true;
+ }
+
+ public void stop() {
+ mNetworkInterface = null;
+ mHwAddr = null;
+ updateLocalRoutes(null);
+ updateRaParams(null);
+
+ if (mRaDaemon != null) {
+ mRaDaemon.stop();
+ mRaDaemon = null;
+ }
+ }
+
+ // IPv6TetheringCoordinator sends updates with carefully curated IPv6-only
+ // LinkProperties. These have extraneous data filtered out and only the
+ // necessary prefixes included (per its prefix distribution policy).
+ //
+ // TODO: Evaluate using a data structure than is more directly suited to
+ // communicating only the relevant information.
+ public void updateUpstreamIPv6LinkProperties(LinkProperties v6only) {
+ if (mRaDaemon == null) return;
+
+ if (v6only == null) {
+ updateLocalRoutes(null);
+ updateRaParams(null);
+ return;
+ }
+
+ RaParams params = new RaParams();
+ params.mtu = v6only.getMtu();
+ params.hasDefaultRoute = v6only.hasIPv6DefaultRoute();
+
+ ArrayList<RouteInfo> localRoutes = new ArrayList<RouteInfo>();
+ for (LinkAddress linkAddr : v6only.getLinkAddresses()) {
+ final IpPrefix prefix = new IpPrefix(linkAddr.getAddress(),
+ linkAddr.getPrefixLength());
+
+ // Accumulate routes representing "prefixes to be assigned to the
+ // local interface", for subsequent addition to the local network
+ // in the routing rules.
+ localRoutes.add(new RouteInfo(prefix, null, mIfName));
+
+ params.prefixes.add(prefix);
+ }
+
+ // We need to be able to send unicast RAs, and clients might like to
+ // ping the default router's link-local address, so add that as well.
+ localRoutes.add(new RouteInfo(new IpPrefix("fe80::/64"), null, mIfName));
+
+ // TODO: Add a local interface address, update dnsmasq to listen on the
+ // new address, and use only that address as a DNS server.
+ for (InetAddress dnsServer : v6only.getDnsServers()) {
+ if (dnsServer instanceof Inet6Address) {
+ params.dnses.add((Inet6Address) dnsServer);
+ }
+ }
+
+ updateLocalRoutes(localRoutes);
+ updateRaParams(params);
+ }
+
+ private void updateLocalRoutes(ArrayList<RouteInfo> localRoutes) {
+ if (localRoutes != null) {
+ // TODO: Compare with mLastLocalRoutes and take appropriate
+ // appropriate action on the difference between the two.
+
+ if (!localRoutes.isEmpty()) {
+ try {
+ mNMService.addInterfaceToLocalNetwork(mIfName, localRoutes);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to add IPv6 routes to local table: ", e);
+ }
+ }
+ } else {
+ if (mLastLocalRoutes != null && !mLastLocalRoutes.isEmpty()) {
+ // TODO: Remove only locally added network routes.
+ // mNMSwervice.removeInterfaceFromLocalNetwork(mIfName);
+ }
+ }
+
+ mLastLocalRoutes = localRoutes;
+ }
+
+ private void updateRaParams(RaParams params) {
+ if (mRaDaemon != null) {
+ // Currently, we send spurious RAs (5) whenever there's any update.
+ // TODO: Compare params with mLastParams to avoid spurious updates.
+ mRaDaemon.buildNewRa(params);
+ }
+
+ mLastRaParams = params;
+ }
+}
diff --git a/services/core/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachine.java b/services/core/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachine.java
index aebeb690d770..9e7cb939cdf0 100644
--- a/services/core/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachine.java
+++ b/services/core/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachine.java
@@ -20,6 +20,7 @@ import android.net.ConnectivityManager;
import android.net.INetworkStatsService;
import android.net.InterfaceConfiguration;
import android.net.LinkAddress;
+import android.net.LinkProperties;
import android.net.NetworkUtils;
import android.os.INetworkManagementService;
import android.os.Looper;
@@ -73,6 +74,8 @@ public class TetherInterfaceStateMachine extends StateMachine {
public static final int CMD_SET_DNS_FORWARDERS_ERROR = BASE_IFACE + 11;
// the upstream connection has changed
public static final int CMD_TETHER_CONNECTION_CHANGED = BASE_IFACE + 12;
+ // new IPv6 tethering parameters need to be processed
+ public static final int CMD_IPV6_TETHER_UPDATE = BASE_IFACE + 13;
private final State mInitialState;
private final State mTetheredState;
@@ -84,6 +87,7 @@ public class TetherInterfaceStateMachine extends StateMachine {
private final String mIfaceName;
private final int mInterfaceType;
+ private final IPv6TetheringInterfaceServices mIPv6TetherSvc;
private int mLastError;
private String mMyUpstreamIfaceName; // may change over time
@@ -97,6 +101,7 @@ public class TetherInterfaceStateMachine extends StateMachine {
mTetherController = tetherController;
mIfaceName = ifaceName;
mInterfaceType = interfaceType;
+ mIPv6TetherSvc = new IPv6TetheringInterfaceServices(mIfaceName, mNMService);
mLastError = ConnectivityManager.TETHER_ERROR_NO_ERROR;
mInitialState = new InitialState();
@@ -109,6 +114,10 @@ public class TetherInterfaceStateMachine extends StateMachine {
setInitialState(mInitialState);
}
+ public int interfaceType() {
+ return mInterfaceType;
+ }
+
// configured when we start tethering and unconfig'd on error or conclusion
private boolean configureIfaceIp(boolean enabled) {
if (VDBG) Log.d(TAG, "configureIfaceIp(" + enabled + ")");
@@ -175,6 +184,10 @@ public class TetherInterfaceStateMachine extends StateMachine {
case CMD_INTERFACE_DOWN:
transitionTo(mUnavailableState);
break;
+ case CMD_IPV6_TETHER_UPDATE:
+ mIPv6TetherSvc.updateUpstreamIPv6LinkProperties(
+ (LinkProperties) message.obj);
+ break;
default:
retValue = false;
break;
@@ -200,6 +213,11 @@ public class TetherInterfaceStateMachine extends StateMachine {
transitionTo(mInitialState);
return;
}
+
+ if (!mIPv6TetherSvc.start()) {
+ Log.e(TAG, "Failed to start IPv6TetheringInterfaceServices");
+ }
+
if (DBG) Log.d(TAG, "Tethered " + mIfaceName);
mTetherController.notifyInterfaceStateChange(
mIfaceName, TetherInterfaceStateMachine.this,
@@ -211,6 +229,7 @@ public class TetherInterfaceStateMachine extends StateMachine {
// Note that at this point, we're leaving the tethered state. We can fail any
// of these operations, but it doesn't really change that we have to try them
// all in sequence.
+ mIPv6TetherSvc.stop();
cleanupUpstream();
try {
@@ -287,6 +306,10 @@ public class TetherInterfaceStateMachine extends StateMachine {
}
mMyUpstreamIfaceName = newUpstreamIfaceName;
break;
+ case CMD_IPV6_TETHER_UPDATE:
+ mIPv6TetherSvc.updateUpstreamIPv6LinkProperties(
+ (LinkProperties) message.obj);
+ break;
case CMD_IP_FORWARDING_ENABLE_ERROR:
case CMD_IP_FORWARDING_DISABLE_ERROR:
case CMD_START_TETHERING_ERROR:
diff --git a/services/core/java/com/android/server/media/MediaSessionRecord.java b/services/core/java/com/android/server/media/MediaSessionRecord.java
index 29c54e9bf78c..88d6c14fb5de 100644
--- a/services/core/java/com/android/server/media/MediaSessionRecord.java
+++ b/services/core/java/com/android/server/media/MediaSessionRecord.java
@@ -454,7 +454,7 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
@Override
public String toString() {
- return mPackageName + "/" + mTag;
+ return mPackageName + "/" + mTag + " (uid=" + mUserId + ")";
}
private void postAdjustLocalVolume(final int stream, final int direction, final int flags,
diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java
index a4d2cd25cb14..a3f09c03ae74 100644
--- a/services/core/java/com/android/server/media/MediaSessionService.java
+++ b/services/core/java/com/android/server/media/MediaSessionService.java
@@ -47,10 +47,12 @@ import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.PowerManager;
+import android.os.Process;
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.ServiceManager;
import android.os.UserHandle;
+import android.os.UserManager;
import android.provider.Settings;
import android.speech.RecognizerIntent;
import android.text.TextUtils;
@@ -67,6 +69,7 @@ import com.android.server.Watchdog.Monitor;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
/**
@@ -97,7 +100,9 @@ public class MediaSessionService extends SystemService implements Monitor {
private ContentResolver mContentResolver;
private SettingsObserver mSettingsObserver;
- private int mCurrentUserId = -1;
+ // List of user IDs running in the foreground.
+ // Multiple users can be in the foreground if the work profile is on.
+ private final List<Integer> mCurrentUserIdList = new ArrayList<>();
// Used to notify system UI when remote volume was changed. TODO find a
// better way to handle this.
@@ -181,22 +186,26 @@ public class MediaSessionService extends SystemService implements Monitor {
}
@Override
- public void onStartUser(int userHandle) {
+ public void onStartUser(int userId) {
+ if (DEBUG) Log.d(TAG, "onStartUser: " + userId);
updateUser();
}
@Override
- public void onSwitchUser(int userHandle) {
+ public void onSwitchUser(int userId) {
+ if (DEBUG) Log.d(TAG, "onSwitchUser: " + userId);
updateUser();
}
@Override
- public void onStopUser(int userHandle) {
+ public void onStopUser(int userId) {
+ if (DEBUG) Log.d(TAG, "onStopUser: " + userId);
synchronized (mLock) {
- UserRecord user = mUserRecords.get(userHandle);
+ UserRecord user = mUserRecords.get(userId);
if (user != null) {
destroyUserLocked(user);
}
+ updateUser();
}
}
@@ -228,18 +237,23 @@ public class MediaSessionService extends SystemService implements Monitor {
private void updateUser() {
synchronized (mLock) {
- int userId = ActivityManager.getCurrentUser();
- if (mCurrentUserId != userId) {
- final int oldUserId = mCurrentUserId;
- mCurrentUserId = userId; // do this first
-
- UserRecord oldUser = mUserRecords.get(oldUserId);
- if (oldUser != null) {
- oldUser.stopLocked();
+ UserManager manager = (UserManager) getContext().getSystemService(Context.USER_SERVICE);
+ int currentUser = ActivityManager.getCurrentUser();
+ int[] userIds = manager.getEnabledProfileIds(currentUser);
+ mCurrentUserIdList.clear();
+ if (userIds != null && userIds.length > 0) {
+ for (int userId : userIds) {
+ mCurrentUserIdList.add(userId);
+ }
+ } else {
+ // This shouldn't happen.
+ Log.w(TAG, "Failed to get enabled profiles.");
+ mCurrentUserIdList.add(currentUser);
+ }
+ for (int userId : mCurrentUserIdList) {
+ if (mUserRecords.get(userId) == null) {
+ mUserRecords.put(userId, new UserRecord(getContext(), userId));
}
-
- UserRecord newUser = getOrCreateUser(userId);
- newUser.startLocked();
}
}
}
@@ -272,7 +286,6 @@ public class MediaSessionService extends SystemService implements Monitor {
* @param user The user to dispose of
*/
private void destroyUserLocked(UserRecord user) {
- user.stopLocked();
user.destroyLocked();
mUserRecords.remove(user.mUserId);
}
@@ -436,9 +449,9 @@ public class MediaSessionService extends SystemService implements Monitor {
}
mAllSessions.add(session);
- mPriorityStack.addSession(session);
+ mPriorityStack.addSession(session, mCurrentUserIdList.contains(userId));
- UserRecord user = getOrCreateUser(userId);
+ UserRecord user = mUserRecords.get(userId);
user.addSessionLocked(session);
mHandler.post(MessageHandler.MSG_SESSIONS_CHANGED, userId, 0);
@@ -449,15 +462,6 @@ public class MediaSessionService extends SystemService implements Monitor {
return session;
}
- private UserRecord getOrCreateUser(int userId) {
- UserRecord user = mUserRecords.get(userId);
- if (user == null) {
- user = new UserRecord(getContext(), userId);
- mUserRecords.put(userId, user);
- }
- return user;
- }
-
private int findIndexOfSessionsListenerLocked(IActiveSessionsListener listener) {
for (int i = mSessionsListeners.size() - 1; i >= 0; i--) {
if (mSessionsListeners.get(i).mListener.asBinder() == listener.asBinder()) {
@@ -536,13 +540,6 @@ public class MediaSessionService extends SystemService implements Monitor {
restoreMediaButtonReceiver();
}
- public void startLocked() {
- }
-
- public void stopLocked() {
- // nothing for now
- }
-
public void destroyLocked() {
for (int i = mSessions.size() - 1; i >= 0; i--) {
MediaSessionRecord session = mSessions.get(i);
@@ -578,7 +575,7 @@ public class MediaSessionService extends SystemService implements Monitor {
private void restoreMediaButtonReceiver() {
String receiverName = Settings.Secure.getStringForUser(mContentResolver,
- Settings.System.MEDIA_BUTTON_RECEIVER, UserHandle.USER_CURRENT);
+ Settings.System.MEDIA_BUTTON_RECEIVER, mUserId);
if (!TextUtils.isEmpty(receiverName)) {
ComponentName eventReceiver = ComponentName.unflattenFromString(receiverName);
if (eventReceiver == null) {
@@ -767,12 +764,22 @@ public class MediaSessionService extends SystemService implements Monitor {
synchronized (mLock) {
// If we don't have a media button receiver to fall back on
// include non-playing sessions for dispatching
- UserRecord ur = mUserRecords.get(mCurrentUserId);
- boolean useNotPlayingSessions = (ur == null) ||
- (ur.mLastMediaButtonReceiver == null
- && ur.mRestoredMediaButtonReceiver == null);
- MediaSessionRecord session = mPriorityStack
- .getDefaultMediaButtonSession(mCurrentUserId, useNotPlayingSessions);
+ boolean useNotPlayingSessions = true;
+ for (int userId : mCurrentUserIdList) {
+ UserRecord ur = mUserRecords.get(userId);
+ if (ur.mLastMediaButtonReceiver != null
+ || ur.mRestoredMediaButtonReceiver != null) {
+ useNotPlayingSessions = false;
+ break;
+ }
+ }
+
+ if (DEBUG) {
+ Log.d(TAG, "dispatchMediaKeyEvent, useNotPlayingSessions="
+ + useNotPlayingSessions);
+ }
+ MediaSessionRecord session = mPriorityStack.getDefaultMediaButtonSession(
+ mCurrentUserIdList, useNotPlayingSessions);
if (isVoiceKey(keyEvent.getKeyCode())) {
handleVoiceKeyEventLocked(keyEvent, needWakeLock, session);
} else {
@@ -786,13 +793,11 @@ public class MediaSessionService extends SystemService implements Monitor {
@Override
public void dispatchAdjustVolume(int suggestedStream, int delta, int flags) {
- final int pid = Binder.getCallingPid();
- final int uid = Binder.getCallingUid();
final long token = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
MediaSessionRecord session = mPriorityStack
- .getDefaultVolumeSession(mCurrentUserId);
+ .getDefaultVolumeSession(mCurrentUserIdList);
dispatchAdjustVolumeLocked(suggestedStream, delta, flags, session);
}
} finally {
@@ -899,7 +904,7 @@ public class MediaSessionService extends SystemService implements Monitor {
}
} else {
session.adjustVolume(direction, flags, getContext().getPackageName(),
- UserHandle.myUserId(), true);
+ Process.SYSTEM_UID, true);
}
}
@@ -946,13 +951,16 @@ public class MediaSessionService extends SystemService implements Monitor {
// won't release it later
session.sendMediaButton(keyEvent,
needWakeLock ? mKeyEventReceiver.mLastTimeoutId : -1,
- mKeyEventReceiver, getContext().getApplicationInfo().uid,
+ mKeyEventReceiver, Process.SYSTEM_UID,
getContext().getPackageName());
} else {
// Launch the last PendingIntent we had with priority
- UserRecord user = mUserRecords.get(mCurrentUserId);
- if (user != null && (user.mLastMediaButtonReceiver != null
- || user.mRestoredMediaButtonReceiver != null)) {
+ for (int userId : mCurrentUserIdList) {
+ UserRecord user = mUserRecords.get(userId);
+ if (user.mLastMediaButtonReceiver == null
+ && user.mRestoredMediaButtonReceiver == null) {
+ continue;
+ }
if (DEBUG) {
Log.d(TAG, "Sending media key to last known PendingIntent "
+ user.mLastMediaButtonReceiver + " or restored Intent "
@@ -972,30 +980,30 @@ public class MediaSessionService extends SystemService implements Monitor {
} else {
mediaButtonIntent.setComponent(user.mRestoredMediaButtonReceiver);
getContext().sendBroadcastAsUser(mediaButtonIntent,
- new UserHandle(mCurrentUserId));
+ UserHandle.of(userId));
}
} catch (CanceledException e) {
Log.i(TAG, "Error sending key event to media button receiver "
+ user.mLastMediaButtonReceiver, e);
}
- } else {
- if (DEBUG) {
- Log.d(TAG, "Sending media key ordered broadcast");
- }
- if (needWakeLock) {
- mMediaEventWakeLock.acquire();
- }
- // Fallback to legacy behavior
- Intent keyIntent = new Intent(Intent.ACTION_MEDIA_BUTTON, null);
- keyIntent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
- keyIntent.putExtra(Intent.EXTRA_KEY_EVENT, keyEvent);
- if (needWakeLock) {
- keyIntent.putExtra(EXTRA_WAKELOCK_ACQUIRED,
- WAKELOCK_RELEASE_ON_FINISHED);
- }
- getContext().sendOrderedBroadcastAsUser(keyIntent, UserHandle.CURRENT,
- null, mKeyEventDone, mHandler, Activity.RESULT_OK, null, null);
+ return;
+ }
+ if (DEBUG) {
+ Log.d(TAG, "Sending media key ordered broadcast");
+ }
+ if (needWakeLock) {
+ mMediaEventWakeLock.acquire();
+ }
+ // Fallback to legacy behavior
+ Intent keyIntent = new Intent(Intent.ACTION_MEDIA_BUTTON, null);
+ keyIntent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
+ keyIntent.putExtra(Intent.EXTRA_KEY_EVENT, keyEvent);
+ if (needWakeLock) {
+ keyIntent.putExtra(EXTRA_WAKELOCK_ACQUIRED, WAKELOCK_RELEASE_ON_FINISHED);
}
+ // Send broadcast only to the full user.
+ getContext().sendOrderedBroadcastAsUser(keyIntent, UserHandle.CURRENT,
+ null, mKeyEventDone, mHandler, Activity.RESULT_OK, null, null);
}
}
@@ -1025,6 +1033,7 @@ public class MediaSessionService extends SystemService implements Monitor {
if (voiceIntent != null) {
voiceIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
+ if (DEBUG) Log.d(TAG, "voiceIntent: " + voiceIntent);
getContext().startActivityAsUser(voiceIntent, UserHandle.CURRENT);
}
} catch (ActivityNotFoundException e) {
diff --git a/services/core/java/com/android/server/media/MediaSessionStack.java b/services/core/java/com/android/server/media/MediaSessionStack.java
index cc007eff9075..3327b36536d9 100644
--- a/services/core/java/com/android/server/media/MediaSessionStack.java
+++ b/services/core/java/com/android/server/media/MediaSessionStack.java
@@ -32,7 +32,7 @@ import java.util.List;
* Keeps track of media sessions and their priority for notifications, media
* button dispatch, etc.
*/
-public class MediaSessionStack {
+class MediaSessionStack {
/**
* These are states that usually indicate the user took an action and should
* bump priority regardless of the old state.
@@ -68,13 +68,10 @@ public class MediaSessionStack {
* Checks if a media session is created from the most recent app.
*
* @param record A media session record to be examined.
- * @return true if the media session's package name equals to the most recent app, false
- * otherwise.
+ * @return {@code true} if the media session's package name equals to the most recent app, false
+ * otherwise.
*/
private static boolean isFromMostRecentApp(MediaSessionRecord record) {
- if (ActivityManager.getCurrentUser() != record.getUserId()) {
- return false;
- }
try {
List<ActivityManager.RecentTaskInfo> tasks =
ActivityManagerNative.getDefault().getRecentTasks(1,
@@ -84,9 +81,10 @@ public class MediaSessionStack {
ActivityManager.RECENT_WITH_EXCLUDED, record.getUserId()).getList();
if (tasks != null && !tasks.isEmpty()) {
ActivityManager.RecentTaskInfo recentTask = tasks.get(0);
- if (recentTask.baseIntent != null)
+ if (recentTask.userId == record.getUserId() && recentTask.baseIntent != null) {
return recentTask.baseIntent.getComponent().getPackageName()
.equals(record.getPackageName());
+ }
}
} catch (RemoteException e) {
return false;
@@ -98,11 +96,12 @@ public class MediaSessionStack {
* Add a record to the priority tracker.
*
* @param record The record to add.
+ * @param fromForegroundUser {@code true} if the session is created by the foreground user.
*/
- public void addSession(MediaSessionRecord record) {
+ public void addSession(MediaSessionRecord record, boolean fromForegroundUser) {
mSessions.add(record);
clearCache();
- if (isFromMostRecentApp(record)) {
+ if (fromForegroundUser && isFromMostRecentApp(record)) {
mLastInterestingRecord = record;
}
}
@@ -210,12 +209,13 @@ public class MediaSessionStack {
/**
* Get the highest priority session that can handle media buttons.
*
- * @param userId The user to check.
+ * @param userIdList The user lists to check.
* @param includeNotPlaying Return a non-playing session if nothing else is
* available
* @return The default media button session or null.
*/
- public MediaSessionRecord getDefaultMediaButtonSession(int userId, boolean includeNotPlaying) {
+ public MediaSessionRecord getDefaultMediaButtonSession(
+ List<Integer> userIdList, boolean includeNotPlaying) {
if (mGlobalPrioritySession != null && mGlobalPrioritySession.isActive()) {
return mGlobalPrioritySession;
}
@@ -223,7 +223,7 @@ public class MediaSessionStack {
return mCachedButtonReceiver;
}
ArrayList<MediaSessionRecord> records = getPriorityListLocked(true,
- MediaSession.FLAG_HANDLES_MEDIA_BUTTONS, userId);
+ MediaSession.FLAG_HANDLES_MEDIA_BUTTONS, userIdList);
if (records.size() > 0) {
MediaSessionRecord record = records.get(0);
if (record.isPlaybackActive(false)) {
@@ -248,14 +248,14 @@ public class MediaSessionStack {
return mCachedButtonReceiver;
}
- public MediaSessionRecord getDefaultVolumeSession(int userId) {
+ public MediaSessionRecord getDefaultVolumeSession(List<Integer> userIdList) {
if (mGlobalPrioritySession != null && mGlobalPrioritySession.isActive()) {
return mGlobalPrioritySession;
}
if (mCachedVolumeDefault != null) {
return mCachedVolumeDefault;
}
- ArrayList<MediaSessionRecord> records = getPriorityListLocked(true, 0, userId);
+ ArrayList<MediaSessionRecord> records = getPriorityListLocked(true, 0, userIdList);
int size = records.size();
for (int i = 0; i < size; i++) {
MediaSessionRecord record = records.get(i);
@@ -298,6 +298,13 @@ public class MediaSessionStack {
}
}
+ private ArrayList<MediaSessionRecord> getPriorityListLocked(boolean activeOnly, int withFlags,
+ int userId) {
+ List<Integer> userIdList = new ArrayList<>();
+ userIdList.add(userId);
+ return getPriorityListLocked(activeOnly, withFlags, userIdList);
+ }
+
/**
* Get a priority sorted list of sessions. Can filter to only return active
* sessions or sessions with specific flags.
@@ -306,22 +313,23 @@ public class MediaSessionStack {
* all sessions.
* @param withFlags Only return sessions with all the specified flags set. 0
* returns all sessions.
- * @param userId The user to get sessions for. {@link UserHandle#USER_ALL}
+ * @param userIdList The user to get sessions for. {@link UserHandle#USER_ALL}
* will return sessions for all users.
* @return The priority sorted list of sessions.
*/
private ArrayList<MediaSessionRecord> getPriorityListLocked(boolean activeOnly, int withFlags,
- int userId) {
+ List<Integer> userIdList) {
ArrayList<MediaSessionRecord> result = new ArrayList<MediaSessionRecord>();
int lastLocalIndex = 0;
int lastActiveIndex = 0;
int lastPublishedIndex = 0;
+ boolean filterUser = !userIdList.contains(UserHandle.USER_ALL);
int size = mSessions.size();
for (int i = 0; i < size; i++) {
final MediaSessionRecord session = mSessions.get(i);
- if (userId != UserHandle.USER_ALL && userId != session.getUserId()) {
+ if (filterUser && !userIdList.contains(session.getUserId())) {
// Filter out sessions for the wrong user
continue;
}
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index ec77dafb2914..8d19a24753a2 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -1851,7 +1851,7 @@ public class NotificationManagerService extends SystemService {
enforceSystemOrSystemUIOrVolume("INotificationManager.setZenMode");
final long identity = Binder.clearCallingIdentity();
try {
- mZenModeHelper.setManualZenMode(mode, conditionId, reason);
+ mZenModeHelper.setManualZenMode(mode, conditionId, null, reason);
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -1928,7 +1928,7 @@ public class NotificationManagerService extends SystemService {
if (zen == -1) throw new IllegalArgumentException("Invalid filter: " + filter);
final long identity = Binder.clearCallingIdentity();
try {
- mZenModeHelper.setManualZenMode(zen, null, "setInterruptionFilter");
+ mZenModeHelper.setManualZenMode(zen, null, pkg, "setInterruptionFilter");
} finally {
Binder.restoreCallingIdentity(identity);
}
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index 6864ed898ada..8c9dc3ba60f2 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -54,7 +54,6 @@ import android.service.notification.ZenModeConfig;
import android.service.notification.ZenModeConfig.EventInfo;
import android.service.notification.ZenModeConfig.ScheduleInfo;
import android.service.notification.ZenModeConfig.ZenRule;
-import android.text.TextUtils;
import android.util.AndroidRuntimeException;
import android.util.Log;
import android.util.SparseArray;
@@ -229,7 +228,7 @@ public class ZenModeHelper {
public void requestFromListener(ComponentName name, int filter) {
final int newZen = NotificationManager.zenModeFromInterruptionFilter(filter, -1);
if (newZen != -1) {
- setManualZenMode(newZen, null,
+ setManualZenMode(newZen, null, name != null ? name.getPackageName() : null,
"listener:" + (name != null ? name.flattenToShortString() : null));
}
}
@@ -452,11 +451,11 @@ public class ZenModeHelper {
rule.creationTime);
}
- public void setManualZenMode(int zenMode, Uri conditionId, String reason) {
- setManualZenMode(zenMode, conditionId, reason, true /*setRingerMode*/);
+ public void setManualZenMode(int zenMode, Uri conditionId, String caller, String reason) {
+ setManualZenMode(zenMode, conditionId, reason, caller, true /*setRingerMode*/);
}
- private void setManualZenMode(int zenMode, Uri conditionId, String reason,
+ private void setManualZenMode(int zenMode, Uri conditionId, String reason, String caller,
boolean setRingerMode) {
ZenModeConfig newConfig;
synchronized (mConfig) {
@@ -478,6 +477,7 @@ public class ZenModeHelper {
newRule.enabled = true;
newRule.zenMode = zenMode;
newRule.conditionId = conditionId;
+ newRule.enabler = caller;
newConfig.manualRule = newRule;
}
setConfigLocked(newConfig, reason, setRingerMode);
@@ -950,7 +950,8 @@ public class ZenModeHelper {
break;
}
if (newZen != -1) {
- setManualZenMode(newZen, null, "ringerModeInternal", false /*setRingerMode*/);
+ setManualZenMode(newZen, null, "ringerModeInternal", null,
+ false /*setRingerMode*/);
}
if (isChange || newZen != -1 || ringerModeExternal != ringerModeExternalOut) {
@@ -988,7 +989,8 @@ public class ZenModeHelper {
break;
}
if (newZen != -1) {
- setManualZenMode(newZen, null, "ringerModeExternal", false /*setRingerMode*/);
+ setManualZenMode(newZen, null, "ringerModeExternal", caller,
+ false /*setRingerMode*/);
}
ZenLog.traceSetRingerModeExternal(ringerModeOld, ringerModeNew, caller,
diff --git a/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
index c1219bf84562..1cff926d14e1 100644
--- a/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
@@ -629,6 +629,7 @@ final class DefaultPermissionGrantPolicy {
grantRuntimePermissionsLPw(dialerPackage, CONTACTS_PERMISSIONS, userId);
grantRuntimePermissionsLPw(dialerPackage, SMS_PERMISSIONS, userId);
grantRuntimePermissionsLPw(dialerPackage, MICROPHONE_PERMISSIONS, userId);
+ grantRuntimePermissionsLPw(dialerPackage, CAMERA_PERMISSIONS, userId);
}
}
@@ -666,6 +667,7 @@ final class DefaultPermissionGrantPolicy {
grantRuntimePermissionsLPw(dialerPackage, CONTACTS_PERMISSIONS, false, true, userId);
grantRuntimePermissionsLPw(dialerPackage, SMS_PERMISSIONS, false, true, userId);
grantRuntimePermissionsLPw(dialerPackage, MICROPHONE_PERMISSIONS, false, true, userId);
+ grantRuntimePermissionsLPw(dialerPackage, CAMERA_PERMISSIONS, false, true, userId);
}
}
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index 83af0173c514..6a56fa6e629b 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -182,6 +182,10 @@ public class PackageInstallerService extends IPackageInstaller.Stub {
*/
private final Random mRandom = new SecureRandom();
+ /** All sessions allocated */
+ @GuardedBy("mSessions")
+ private final SparseBooleanArray mAllocatedSessions = new SparseBooleanArray();
+
@GuardedBy("mSessions")
private final SparseArray<PackageInstallerSession> mSessions = new SparseArray<>();
@@ -365,6 +369,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub {
// keep details around for dumpsys.
mHistoricalSessions.put(session.sessionId, session);
}
+ mAllocatedSessions.put(session.sessionId, true);
}
}
}
@@ -666,23 +671,26 @@ public class PackageInstallerService extends IPackageInstaller.Stub {
"Too many historical sessions for UID " + callingUid);
}
- final long createdMillis = System.currentTimeMillis();
sessionId = allocateSessionIdLocked();
+ }
- // We're staging to exactly one location
- File stageDir = null;
- String stageCid = null;
- if ((params.installFlags & PackageManager.INSTALL_INTERNAL) != 0) {
- final boolean isEphemeral =
- (params.installFlags & PackageManager.INSTALL_EPHEMERAL) != 0;
- stageDir = buildStageDir(params.volumeUuid, sessionId, isEphemeral);
- } else {
- stageCid = buildExternalStageCid(sessionId);
- }
+ final long createdMillis = System.currentTimeMillis();
+ // We're staging to exactly one location
+ File stageDir = null;
+ String stageCid = null;
+ if ((params.installFlags & PackageManager.INSTALL_INTERNAL) != 0) {
+ final boolean isEphemeral =
+ (params.installFlags & PackageManager.INSTALL_EPHEMERAL) != 0;
+ stageDir = buildStageDir(params.volumeUuid, sessionId, isEphemeral);
+ } else {
+ stageCid = buildExternalStageCid(sessionId);
+ }
- session = new PackageInstallerSession(mInternalCallback, mContext, mPm,
- mInstallThread.getLooper(), sessionId, userId, installerPackageName, callingUid,
- params, createdMillis, stageDir, stageCid, false, false);
+ session = new PackageInstallerSession(mInternalCallback, mContext, mPm,
+ mInstallThread.getLooper(), sessionId, userId, installerPackageName, callingUid,
+ params, createdMillis, stageDir, stageCid, false, false);
+
+ synchronized (mSessions) {
mSessions.put(sessionId, session);
}
@@ -765,8 +773,8 @@ public class PackageInstallerService extends IPackageInstaller.Stub {
int sessionId;
do {
sessionId = mRandom.nextInt(Integer.MAX_VALUE - 1) + 1;
- if (mSessions.get(sessionId) == null && mHistoricalSessions.get(sessionId) == null
- && !mLegacySessions.get(sessionId, false)) {
+ if (!mAllocatedSessions.get(sessionId, false)) {
+ mAllocatedSessions.put(sessionId, true);
return sessionId;
}
} while (n++ < 32);
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 455e1faabf74..5980715c5358 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -159,7 +159,6 @@ import android.content.pm.PermissionInfo;
import android.content.pm.ProviderInfo;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
-import android.content.pm.ShortcutServiceInternal;
import android.content.pm.Signature;
import android.content.pm.UserInfo;
import android.content.pm.VerifierDeviceIdentity;
@@ -11439,9 +11438,6 @@ public class PackageManagerService extends IPackageManager.Stub {
} else {
resolvedUserIds = userIds;
}
- final ShortcutServiceInternal shortcutService =
- LocalServices.getService(ShortcutServiceInternal.class);
-
for (int id : resolvedUserIds) {
final Intent intent = new Intent(action,
pkg != null ? Uri.fromParts("package", pkg, null) : null);
@@ -11466,10 +11462,6 @@ public class PackageManagerService extends IPackageManager.Stub {
+ intent.toShortString(false, true, false, false)
+ " " + intent.getExtras(), here);
}
- // TODO b/29385425 Consider making lifecycle callbacks for this.
- if (shortcutService != null) {
- shortcutService.onPackageBroadcast(intent);
- }
am.broadcastIntent(null, intent, null, finishedReceiver,
0, null, null, null, android.app.AppOpsManager.OP_NONE,
null, finishedReceiver != null, false, id);
@@ -20443,12 +20435,7 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
}
}
- void onBeforeUserStartUninitialized(final int userId) {
- synchronized (mPackages) {
- if (mSettings.areDefaultRuntimePermissionsGrantedLPr(userId)) {
- return;
- }
- }
+ void onNewUserCreated(final int userId) {
mDefaultPermissionPolicy.grantDefaultPermissions(userId);
// If permission review for legacy apps is required, we represent
// dagerous permissions for such apps as always granted runtime
diff --git a/services/core/java/com/android/server/pm/ShortcutPackage.java b/services/core/java/com/android/server/pm/ShortcutPackage.java
index 1a4e4e0ad80b..b94d0f0dbd1c 100644
--- a/services/core/java/com/android/server/pm/ShortcutPackage.java
+++ b/services/core/java/com/android/server/pm/ShortcutPackage.java
@@ -1185,8 +1185,8 @@ class ShortcutPackage extends ShortcutPackageItem {
private static void saveShortcut(XmlSerializer out, ShortcutInfo si, boolean forBackup)
throws IOException, XmlPullParserException {
if (forBackup) {
- if (!si.isPinned()) {
- return; // Backup only pinned icons.
+ if (!(si.isPinned() && si.isEnabled())) {
+ return; // We only backup pinned shortcuts that are enabled.
}
}
out.startTag(null, TAG_SHORTCUT);
diff --git a/services/core/java/com/android/server/pm/ShortcutPendingTasks.java b/services/core/java/com/android/server/pm/ShortcutPendingTasks.java
deleted file mode 100644
index a5ace56fee1f..000000000000
--- a/services/core/java/com/android/server/pm/ShortcutPendingTasks.java
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * 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.server.pm;
-
-import android.annotation.NonNull;
-import android.util.Slog;
-
-import java.io.PrintWriter;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.atomic.AtomicLong;
-import java.util.function.BooleanSupplier;
-import java.util.function.Consumer;
-import java.util.logging.Handler;
-
-/**
- * Used by {@link ShortcutService} to register tasks to be executed on Handler and also wait for
- * all pending tasks.
- *
- * Tasks can be registered with {@link #addTask(Runnable)}. Call {@link #waitOnAllTasks()} to wait
- * on all tasks that have been registered.
- *
- * In order to avoid deadlocks, {@link #waitOnAllTasks} MUST NOT be called with any lock held, nor
- * on the handler thread. These conditions are checked by {@link #mWaitThreadChecker} and wtf'ed.
- *
- * During unit tests, we can't run tasks asynchronously, so we just run Runnables synchronously,
- * which also means the "is lock held" check doesn't work properly during unit tests (e.g. normally
- * when a Runnable is executed on a Handler, the thread doesn't hold any lock, but during the tests
- * we just run a Runnable on the thread that registers it, so the thread may or may not hold locks.)
- * So unfortunately we have to disable {@link #mWaitThreadChecker} during unit tests.
- *
- * Because of the complications like those, this class should be used only for specific purposes:
- * - {@link #addTask(Runnable)} should only be used to register tasks on callbacks from lower level
- * services like the package manager or the activity manager.
- *
- * - {@link #waitOnAllTasks} should only be called at the entry point of RPC calls (or the test only
- * accessors}.
- */
-public class ShortcutPendingTasks {
- private static final String TAG = "ShortcutPendingTasks";
-
- private static final boolean DEBUG = false || ShortcutService.DEBUG; // DO NOT SUBMIT WITH TRUE.
-
- private final Consumer<Runnable> mRunner;
-
- private final BooleanSupplier mWaitThreadChecker;
-
- private final Consumer<Throwable> mExceptionHandler;
-
- /** # of tasks in the queue, including the running one. */
- private final AtomicInteger mRunningTaskCount = new AtomicInteger();
-
- /** For dumpsys */
- private final AtomicLong mLastTaskStartTime = new AtomicLong();
-
- /**
- * Constructor. In order to allow injection during unit tests, it doesn't take a
- * {@link Handler} directly, and instead takes {@code runner} which will post an argument
- * to a handler.
- */
- public ShortcutPendingTasks(Consumer<Runnable> runner, BooleanSupplier waitThreadChecker,
- Consumer<Throwable> exceptionHandler) {
- mRunner = runner;
- mWaitThreadChecker = waitThreadChecker;
- mExceptionHandler = exceptionHandler;
- }
-
- private static void dlog(String message) {
- if (DEBUG) {
- Slog.d(TAG, message);
- }
- }
-
- /**
- * Block until all tasks that are already queued finish. DO NOT call it while holding any lock
- * or on the handler thread.
- */
- public boolean waitOnAllTasks() {
- dlog("waitOnAllTasks: enter");
- try {
- // Make sure it's not holding the lock.
- if (!mWaitThreadChecker.getAsBoolean()) {
- return false;
- }
-
- // Optimize for the no-task case.
- if (mRunningTaskCount.get() == 0) {
- return true;
- }
-
- final CountDownLatch latch = new CountDownLatch(1);
-
- addTask(latch::countDown);
-
- for (; ; ) {
- try {
- if (latch.await(1, TimeUnit.SECONDS)) {
- return true;
- }
- dlog("waitOnAllTasks: Task(s) still running...");
- } catch (InterruptedException ignore) {
- }
- }
- } finally {
- dlog("waitOnAllTasks: exit");
- }
- }
-
- /**
- * Add a new task. This operation is lock-free.
- */
- public void addTask(Runnable task) {
- mRunningTaskCount.incrementAndGet();
- mLastTaskStartTime.set(System.currentTimeMillis());
-
- dlog("Task registered");
-
- mRunner.accept(() -> {
- try {
- dlog("Task started");
-
- task.run();
- } catch (Throwable th) {
- mExceptionHandler.accept(th);
- } finally {
- dlog("Task finished");
- mRunningTaskCount.decrementAndGet();
- }
- });
- }
-
- public void dump(@NonNull PrintWriter pw, @NonNull String prefix) {
- pw.print(prefix);
- pw.print("Pending tasks: # running tasks: ");
- pw.println(mRunningTaskCount.get());
-
- pw.print(prefix);
- pw.print(" Last task started time: ");
- final long lastStarted = mLastTaskStartTime.get();
- pw.print(" [");
- pw.print(lastStarted);
- pw.print("] ");
- pw.println(ShortcutService.formatTime(lastStarted));
- }
-}
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index a9018b3a5a84..5f8cbbf0544b 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -49,7 +49,6 @@ import android.graphics.Bitmap.CompressFormat;
import android.graphics.Canvas;
import android.graphics.RectF;
import android.graphics.drawable.Icon;
-import android.net.Uri;
import android.os.Binder;
import android.os.Environment;
import android.os.FileUtils;
@@ -82,6 +81,7 @@ import android.view.IWindowManager;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.content.PackageMonitor;
import com.android.internal.os.BackgroundThread;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.Preconditions;
@@ -122,6 +122,9 @@ import java.util.function.Predicate;
/**
* TODO:
+ * - Deal with the async nature of PACKAGE_ADD. Basically when a publisher does anything after
+ * it's upgraded, the manager should make sure the upgrade process has been executed.
+ *
* - getIconMaxWidth()/getIconMaxHeight() should use xdpi and ydpi.
* -> But TypedValue.applyDimension() doesn't differentiate x and y..?
*
@@ -301,8 +304,6 @@ public class ShortcutService extends IShortcutService.Stub {
private final AtomicBoolean mBootCompleted = new AtomicBoolean();
- private final ShortcutPendingTasks mPendingTasks;
-
private static final int PACKAGE_MATCH_FLAGS =
PackageManager.MATCH_DIRECT_BOOT_AWARE
| PackageManager.MATCH_DIRECT_BOOT_UNAWARE
@@ -376,41 +377,16 @@ public class ShortcutService extends IShortcutService.Stub {
mUsageStatsManagerInternal = Preconditions.checkNotNull(
LocalServices.getService(UsageStatsManagerInternal.class));
- mPendingTasks = new ShortcutPendingTasks(
- this::injectPostToHandler,
- this::injectCheckPendingTaskWaitThread,
- throwable -> wtf(throwable.getMessage(), throwable));
-
if (onlyForPackageManagerApis) {
return; // Don't do anything further. For unit tests only.
}
+ mPackageMonitor.register(context, looper, UserHandle.ALL, /* externalStorage= */ false);
+
injectRegisterUidObserver(mUidObserver, ActivityManager.UID_OBSERVER_PROCSTATE
| ActivityManager.UID_OBSERVER_GONE);
}
- /**
- * Check whether {@link ShortcutPendingTasks#waitOnAllTasks()} can be called on the current
- * thread.
- *
- * During unit tests, all tasks are executed synchronously which makes the lock held check would
- * misfire, so we override this method to always return true.
- */
- @VisibleForTesting
- boolean injectCheckPendingTaskWaitThread() {
- // We shouldn't wait while holding mLock. We should never do this so wtf().
- if (Thread.holdsLock(mLock)) {
- wtf("waitOnAllTasks() called while holding the lock");
- return false;
- }
- // This shouldn't be called on the handler thread either.
- if (Thread.currentThread() == mHandler.getLooper().getThread()) {
- wtf("waitOnAllTasks() called on handler thread");
- return false;
- }
- return true;
- }
-
void logDurationStat(int statId, long start) {
synchronized (mStatLock) {
mCountStats[statId]++;
@@ -1516,8 +1492,6 @@ public class ShortcutService extends IShortcutService.Stub {
@UserIdInt int userId) {
verifyCaller(packageName, userId);
- mPendingTasks.waitOnAllTasks();
-
final List<ShortcutInfo> newShortcuts = (List<ShortcutInfo>) shortcutInfoList.getList();
final int size = newShortcuts.size();
@@ -1567,8 +1541,6 @@ public class ShortcutService extends IShortcutService.Stub {
@UserIdInt int userId) {
verifyCaller(packageName, userId);
- mPendingTasks.waitOnAllTasks();
-
final List<ShortcutInfo> newShortcuts = (List<ShortcutInfo>) shortcutInfoList.getList();
final int size = newShortcuts.size();
@@ -1647,8 +1619,6 @@ public class ShortcutService extends IShortcutService.Stub {
@UserIdInt int userId) {
verifyCaller(packageName, userId);
- mPendingTasks.waitOnAllTasks();
-
final List<ShortcutInfo> newShortcuts = (List<ShortcutInfo>) shortcutInfoList.getList();
final int size = newShortcuts.size();
@@ -1699,8 +1669,6 @@ public class ShortcutService extends IShortcutService.Stub {
verifyCaller(packageName, userId);
Preconditions.checkNotNull(shortcutIds, "shortcutIds must be provided");
- mPendingTasks.waitOnAllTasks();
-
synchronized (mLock) {
final ShortcutPackage ps = getPackageShortcutsLocked(packageName, userId);
@@ -1728,8 +1696,6 @@ public class ShortcutService extends IShortcutService.Stub {
verifyCaller(packageName, userId);
Preconditions.checkNotNull(shortcutIds, "shortcutIds must be provided");
- mPendingTasks.waitOnAllTasks();
-
synchronized (mLock) {
final ShortcutPackage ps = getPackageShortcutsLocked(packageName, userId);
@@ -1750,8 +1716,6 @@ public class ShortcutService extends IShortcutService.Stub {
verifyCaller(packageName, userId);
Preconditions.checkNotNull(shortcutIds, "shortcutIds must be provided");
- mPendingTasks.waitOnAllTasks();
-
synchronized (mLock) {
final ShortcutPackage ps = getPackageShortcutsLocked(packageName, userId);
@@ -1774,8 +1738,6 @@ public class ShortcutService extends IShortcutService.Stub {
public void removeAllDynamicShortcuts(String packageName, @UserIdInt int userId) {
verifyCaller(packageName, userId);
- mPendingTasks.waitOnAllTasks();
-
synchronized (mLock) {
getPackageShortcutsLocked(packageName, userId).deleteAllDynamicShortcuts();
}
@@ -1788,9 +1750,6 @@ public class ShortcutService extends IShortcutService.Stub {
public ParceledListSlice<ShortcutInfo> getDynamicShortcuts(String packageName,
@UserIdInt int userId) {
verifyCaller(packageName, userId);
-
- mPendingTasks.waitOnAllTasks();
-
synchronized (mLock) {
return getShortcutsWithQueryLocked(
packageName, userId, ShortcutInfo.CLONE_REMOVE_FOR_CREATOR,
@@ -1802,9 +1761,6 @@ public class ShortcutService extends IShortcutService.Stub {
public ParceledListSlice<ShortcutInfo> getManifestShortcuts(String packageName,
@UserIdInt int userId) {
verifyCaller(packageName, userId);
-
- mPendingTasks.waitOnAllTasks();
-
synchronized (mLock) {
return getShortcutsWithQueryLocked(
packageName, userId, ShortcutInfo.CLONE_REMOVE_FOR_CREATOR,
@@ -1816,9 +1772,6 @@ public class ShortcutService extends IShortcutService.Stub {
public ParceledListSlice<ShortcutInfo> getPinnedShortcuts(String packageName,
@UserIdInt int userId) {
verifyCaller(packageName, userId);
-
- mPendingTasks.waitOnAllTasks();
-
synchronized (mLock) {
return getShortcutsWithQueryLocked(
packageName, userId, ShortcutInfo.CLONE_REMOVE_FOR_CREATOR,
@@ -1848,8 +1801,6 @@ public class ShortcutService extends IShortcutService.Stub {
public int getRemainingCallCount(String packageName, @UserIdInt int userId) {
verifyCaller(packageName, userId);
- mPendingTasks.waitOnAllTasks();
-
synchronized (mLock) {
return mMaxUpdatesPerInterval
- getPackageShortcutsLocked(packageName, userId).getApiCallCount();
@@ -1860,8 +1811,6 @@ public class ShortcutService extends IShortcutService.Stub {
public long getRateLimitResetTime(String packageName, @UserIdInt int userId) {
verifyCaller(packageName, userId);
- mPendingTasks.waitOnAllTasks();
-
synchronized (mLock) {
return getNextResetTimeLocked();
}
@@ -1880,8 +1829,6 @@ public class ShortcutService extends IShortcutService.Stub {
public void reportShortcutUsed(String packageName, String shortcutId, int userId) {
verifyCaller(packageName, userId);
- mPendingTasks.waitOnAllTasks();
-
Preconditions.checkNotNull(shortcutId);
if (DEBUG) {
@@ -1914,8 +1861,6 @@ public class ShortcutService extends IShortcutService.Stub {
public void resetThrottling() {
enforceSystemOrShell();
- mPendingTasks.waitOnAllTasks();
-
resetThrottlingInner(getCallingUserId());
}
@@ -1948,9 +1893,6 @@ public class ShortcutService extends IShortcutService.Stub {
if (DEBUG) {
Slog.d(TAG, "onApplicationActive: package=" + packageName + " userid=" + userId);
}
-
- mPendingTasks.waitOnAllTasks();
-
enforceResetThrottlingPermission();
resetPackageThrottling(packageName, userId);
}
@@ -2113,14 +2055,6 @@ public class ShortcutService extends IShortcutService.Stub {
@Nullable String packageName, @Nullable List<String> shortcutIds,
@Nullable ComponentName componentName,
int queryFlags, int userId) {
-
- // When this method is called from onShortcutChangedInner() in LauncherApps,
- // we're on the handler thread. Do not try to wait on tasks. Not waiting for pending
- // tasks on this specific case should be fine.
- if (Thread.currentThread() != mHandler.getLooper().getThread()) {
- mPendingTasks.waitOnAllTasks();
- }
-
final ArrayList<ShortcutInfo> ret = new ArrayList<>();
final boolean cloneKeyFieldOnly =
((queryFlags & ShortcutQuery.FLAG_GET_KEY_FIELDS_ONLY) != 0);
@@ -2199,8 +2133,6 @@ public class ShortcutService extends IShortcutService.Stub {
Preconditions.checkStringNotEmpty(packageName, "packageName");
Preconditions.checkStringNotEmpty(shortcutId, "shortcutId");
- mPendingTasks.waitOnAllTasks();
-
synchronized (mLock) {
getLauncherShortcutsLocked(callingPackage, userId, launcherUserId)
.attemptToRestoreIfNeededAndSave();
@@ -2238,8 +2170,6 @@ public class ShortcutService extends IShortcutService.Stub {
Preconditions.checkStringNotEmpty(packageName, "packageName");
Preconditions.checkNotNull(shortcutIds, "shortcutIds");
- mPendingTasks.waitOnAllTasks();
-
synchronized (mLock) {
final ShortcutLauncher launcher =
getLauncherShortcutsLocked(callingPackage, userId, launcherUserId);
@@ -2260,8 +2190,6 @@ public class ShortcutService extends IShortcutService.Stub {
Preconditions.checkStringNotEmpty(packageName, "packageName can't be empty");
Preconditions.checkStringNotEmpty(shortcutId, "shortcutId can't be empty");
- mPendingTasks.waitOnAllTasks();
-
synchronized (mLock) {
getLauncherShortcutsLocked(callingPackage, userId, launcherUserId)
.attemptToRestoreIfNeededAndSave();
@@ -2292,8 +2220,6 @@ public class ShortcutService extends IShortcutService.Stub {
Preconditions.checkNotNull(packageName, "packageName");
Preconditions.checkNotNull(shortcutId, "shortcutId");
- mPendingTasks.waitOnAllTasks();
-
synchronized (mLock) {
getLauncherShortcutsLocked(callingPackage, userId, launcherUserId)
.attemptToRestoreIfNeededAndSave();
@@ -2318,8 +2244,6 @@ public class ShortcutService extends IShortcutService.Stub {
Preconditions.checkNotNull(packageName, "packageName");
Preconditions.checkNotNull(shortcutId, "shortcutId");
- mPendingTasks.waitOnAllTasks();
-
synchronized (mLock) {
getLauncherShortcutsLocked(callingPackage, userId, launcherUserId)
.attemptToRestoreIfNeededAndSave();
@@ -2380,17 +2304,8 @@ public class ShortcutService extends IShortcutService.Stub {
if (DEBUG) {
Slog.d(TAG, "onSystemLocaleChangedNoLock: " + mLocaleChangeSequenceNumber.get());
}
- mPendingTasks.addTask(() -> handleLocaleChanged());
- }
- }
-
- @Override
- public void onPackageBroadcast(Intent intent) {
- if (DEBUG) {
- Slog.d(TAG, "onPackageBroadcast");
+ injectPostToHandler(() -> handleLocaleChanged());
}
- mPendingTasks.addTask(() -> ShortcutService.this.onPackageBroadcast(
- new Intent(intent)));
}
}
@@ -2408,49 +2323,58 @@ public class ShortcutService extends IShortcutService.Stub {
}
}
- private void onPackageBroadcast(Intent intent) {
- final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
- if (userId == UserHandle.USER_NULL) {
- Slog.w(TAG, "Intent broadcast does not contain user handle: " + intent);
- return;
- }
+ /**
+ * Package event callbacks.
+ */
+ @VisibleForTesting
+ final PackageMonitor mPackageMonitor = new PackageMonitor() {
- final String action = intent.getAction();
+ private boolean isUserUnlocked() {
+ return mUserManager.isUserUnlocked(getChangingUserId());
+ }
- if (!mUserManager.isUserUnlocked(userId)) {
- if (DEBUG) {
- Slog.d(TAG, "Ignoring package broadcast " + action + " for locked/stopped user "
- + userId);
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ // clearCallingIdentity is not needed normally, but need to do it for the unit test.
+ final long token = injectClearCallingIdentity();
+ try {
+ super.onReceive(context, intent);
+ } finally {
+ injectRestoreCallingIdentity(token);
}
- return;
}
- final Uri intentUri = intent.getData();
- final String packageName = (intentUri != null) ? intentUri.getSchemeSpecificPart() : null;
- if (packageName == null) {
- Slog.w(TAG, "Intent broadcast does not contain package name: " + intent);
- return;
+ @Override
+ public void onPackageAdded(String packageName, int uid) {
+ if (!isUserUnlocked()) return;
+ handlePackageAdded(packageName, getChangingUserId());
}
- final boolean replacing = intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);
+ @Override
+ public void onPackageUpdateFinished(String packageName, int uid) {
+ if (!isUserUnlocked()) return;
+ handlePackageUpdateFinished(packageName, getChangingUserId());
+ }
- if (Intent.ACTION_PACKAGE_ADDED.equals(action)) {
- if (replacing) {
- handlePackageUpdateFinished(packageName, userId);
- } else {
- handlePackageAdded(packageName, userId);
- }
- } else if (Intent.ACTION_PACKAGE_REMOVED.equals(action)) {
- if (!replacing) {
- handlePackageRemoved(packageName, userId);
- }
- } else if (Intent.ACTION_PACKAGE_CHANGED.equals(action)) {
- handlePackageChanged(packageName, userId);
+ @Override
+ public void onPackageRemoved(String packageName, int uid) {
+ if (!isUserUnlocked()) return;
+ handlePackageRemoved(packageName, getChangingUserId());
+ }
- } else if (Intent.ACTION_PACKAGE_DATA_CLEARED.equals(action)) {
- handlePackageDataCleared(packageName, userId);
+ @Override
+ public void onPackageDataCleared(String packageName, int uid) {
+ if (!isUserUnlocked()) return;
+ handlePackageDataCleared(packageName, getChangingUserId());
}
- }
+
+ @Override
+ public boolean onPackageChanged(String packageName, int uid, String[] components) {
+ if (!isUserUnlocked()) return false;
+ handlePackageChanged(packageName, getChangingUserId());
+ return false; // We don't need to receive onSomePackagesChanged(), so just false.
+ }
+ };
/**
* Called when a user is unlocked.
@@ -3097,9 +3021,6 @@ public class ShortcutService extends IShortcutService.Stub {
pw.println(Log.getStackTraceString(mLastWtfStacktrace));
}
- pw.println();
- mPendingTasks.dump(pw, " ");
-
for (int i = 0; i < mUsers.size(); i++) {
pw.println();
mUsers.valueAt(i).dump(pw, " ");
@@ -3148,8 +3069,6 @@ public class ShortcutService extends IShortcutService.Stub {
enforceShell();
- mPendingTasks.waitOnAllTasks();
-
final int status = (new MyShellCommand()).exec(this, in, out, err, args, resultReceiver);
resultReceiver.send(status, null);
@@ -3176,6 +3095,10 @@ public class ShortcutService extends IShortcutService.Stub {
case "--user":
if (takeUser) {
mUserId = UserHandle.parseUserArg(getNextArgRequired());
+ if (!mUserManager.isUserUnlocked(mUserId)) {
+ throw new CommandException(
+ "User " + mUserId + " is not running or locked");
+ }
break;
}
// fallthrough
@@ -3501,7 +3424,6 @@ public class ShortcutService extends IShortcutService.Stub {
@VisibleForTesting
ShortcutPackage getPackageShortcutForTest(String packageName, int userId) {
- mPendingTasks.waitOnAllTasks();
synchronized (mLock) {
final ShortcutUser user = mUsers.get(userId);
if (user == null) return null;
@@ -3512,12 +3434,8 @@ public class ShortcutService extends IShortcutService.Stub {
@VisibleForTesting
ShortcutInfo getPackageShortcutForTest(String packageName, String shortcutId, int userId) {
- mPendingTasks.waitOnAllTasks();
synchronized (mLock) {
- final ShortcutUser user = mUsers.get(userId);
- if (user == null) return null;
-
- final ShortcutPackage pkg = user.getAllPackagesForTest().get(packageName);
+ final ShortcutPackage pkg = getPackageShortcutForTest(packageName, userId);
if (pkg == null) return null;
return pkg.findShortcutById(shortcutId);
@@ -3552,12 +3470,4 @@ public class ShortcutService extends IShortcutService.Stub {
forEachLoadedUserLocked(u -> u.forAllPackageItems(ShortcutPackageItem::verifyStates));
}
}
-
- ShortcutPendingTasks getPendingTasksForTest() {
- return mPendingTasks;
- }
-
- Object getLockForTest() {
- return mLock;
- }
}
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index d750cbf17f66..68ccbdfceca9 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -1799,6 +1799,18 @@ public class UserManagerService extends IUserManager.Stub {
mUserVersion = USER_VERSION;
Bundle restrictions = new Bundle();
+ try {
+ final String[] defaultFirstUserRestrictions = mContext.getResources().getStringArray(
+ com.android.internal.R.array.config_defaultFirstUserRestrictions);
+ for (String userRestriction : defaultFirstUserRestrictions) {
+ if (UserRestrictionsUtils.isValidRestriction(userRestriction)) {
+ restrictions.putBoolean(userRestriction, true);
+ }
+ }
+ } catch (Resources.NotFoundException e) {
+ Log.e(LOG_TAG, "Couldn't find resource: config_defaultFirstUserRestrictions", e);
+ }
+
synchronized (mRestrictionsLock) {
mBaseUserRestrictions.append(UserHandle.USER_SYSTEM, restrictions);
}
@@ -2304,6 +2316,7 @@ public class UserManagerService extends IUserManager.Stub {
synchronized (mRestrictionsLock) {
mBaseUserRestrictions.append(userId, restrictions);
}
+ mPm.onNewUserCreated(userId);
Intent addedIntent = new Intent(Intent.ACTION_USER_ADDED);
addedIntent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
mContext.sendBroadcastAsUser(addedIntent, UserHandle.ALL,
@@ -2874,10 +2887,6 @@ public class UserManagerService extends IUserManager.Stub {
synchronized (mRestrictionsLock) {
applyUserRestrictionsLR(userId);
}
- UserInfo userInfo = getUserInfoNoChecks(userId);
- if (userInfo != null && !userInfo.isInitialized()) {
- mPm.onBeforeUserStartUninitialized(userId);
- }
}
maybeInitializeDemoMode(userId);
diff --git a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
index c082143e9b5f..04997570b89e 100644
--- a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
+++ b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
@@ -104,7 +104,8 @@ public class UserRestrictionsUtils {
UserManager.DISALLOW_RUN_IN_BACKGROUND,
UserManager.DISALLOW_DATA_ROAMING,
UserManager.DISALLOW_SET_USER_ICON,
- UserManager.DISALLOW_SET_WALLPAPER
+ UserManager.DISALLOW_SET_WALLPAPER,
+ UserManager.DISALLOW_OEM_UNLOCK
});
/**
@@ -138,7 +139,8 @@ public class UserRestrictionsUtils {
*/
private static final Set<String> IMMUTABLE_BY_OWNERS = Sets.newArraySet(
UserManager.DISALLOW_RECORD_AUDIO,
- UserManager.DISALLOW_WALLPAPER
+ UserManager.DISALLOW_WALLPAPER,
+ UserManager.DISALLOW_OEM_UNLOCK
);
/**
@@ -426,6 +428,7 @@ public class UserRestrictionsUtils {
newValue ? 1 : 0);
break;
case UserManager.DISALLOW_FACTORY_RESET:
+ case UserManager.DISALLOW_OEM_UNLOCK:
if (newValue) {
PersistentDataBlockManager manager = (PersistentDataBlockManager) context
.getSystemService(Context.PERSISTENT_DATA_BLOCK_SERVICE);
diff --git a/services/core/java/com/android/server/policy/ImmersiveModeConfirmation.java b/services/core/java/com/android/server/policy/ImmersiveModeConfirmation.java
index 2e32fe381722..c764833e08a6 100644
--- a/services/core/java/com/android/server/policy/ImmersiveModeConfirmation.java
+++ b/services/core/java/com/android/server/policy/ImmersiveModeConfirmation.java
@@ -134,7 +134,7 @@ public class ImmersiveModeConfirmation {
}
public void immersiveModeChangedLw(String pkg, boolean isImmersiveMode,
- boolean userSetupComplete) {
+ boolean userSetupComplete, boolean navBarEmpty) {
mHandler.removeMessages(H.SHOW);
if (isImmersiveMode) {
final boolean disabled = PolicyControl.disableImmersiveConfirmation(pkg);
@@ -144,6 +144,7 @@ public class ImmersiveModeConfirmation {
&& (DEBUG_SHOW_EVERY_TIME || !mConfirmed)
&& userSetupComplete
&& !mVrModeEnabled
+ && !navBarEmpty
&& !UserManager.isDeviceInDemoMode(mContext)) {
mHandler.sendEmptyMessageDelayed(H.SHOW, mShowDelayMs);
}
@@ -152,12 +153,13 @@ public class ImmersiveModeConfirmation {
}
}
- public boolean onPowerKeyDown(boolean isScreenOn, long time, boolean inImmersiveMode) {
+ public boolean onPowerKeyDown(boolean isScreenOn, long time, boolean inImmersiveMode,
+ boolean navBarEmpty) {
if (!isScreenOn && (time - mPanicTime < mPanicThresholdMs)) {
// turning the screen back on within the panic threshold
return mClingWindow == null;
}
- if (isScreenOn && inImmersiveMode) {
+ if (isScreenOn && inImmersiveMode && !navBarEmpty) {
// turning the screen off, remember if we were in immersive mode
mPanicTime = time;
} else {
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 446c75c105e2..fbc727d348a3 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -216,6 +216,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
static final int SHORT_PRESS_SLEEP_GO_TO_SLEEP = 0;
static final int SHORT_PRESS_SLEEP_GO_TO_SLEEP_AND_GO_HOME = 1;
+ static final int PENDING_KEY_NULL = -1;
+
// Controls navigation bar opacity depending on which workspace stacks are currently
// visible.
// Nav bar is always opaque when either the freeform stack or docked stack is visible.
@@ -410,6 +412,10 @@ public class PhoneWindowManager implements WindowManagerPolicy {
volatile boolean mRecentsVisible;
volatile boolean mTvPictureInPictureVisible;
+ // Used to hold the last user key used to wake the device. This helps us prevent up events
+ // from being passed to the foregrounded app without a corresponding down event
+ volatile int mPendingWakeKey = PENDING_KEY_NULL;
+
int mRecentAppsHeldModifiers;
boolean mLanguageSwitchKeyPressed;
@@ -1018,7 +1024,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// Detect user pressing the power button in panic when an application has
// taken over the whole screen.
boolean panic = mImmersiveModeConfirmation.onPowerKeyDown(interactive,
- SystemClock.elapsedRealtime(), isImmersiveMode(mLastSystemUiFlags));
+ SystemClock.elapsedRealtime(), isImmersiveMode(mLastSystemUiFlags),
+ isNavBarEmpty(mLastSystemUiFlags));
if (panic) {
mHandler.post(mHiddenNavPanic);
}
@@ -5560,12 +5567,24 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// key to the application.
result = ACTION_PASS_TO_USER;
isWakeKey = false;
- } else if (!interactive && shouldDispatchInputWhenNonInteractive()) {
+
+ if (interactive) {
+ // If the screen is awake, but the button pressed was the one that woke the device
+ // then don't pass it to the application
+ if (keyCode == mPendingWakeKey && !down) {
+ result = 0;
+ }
+ // Reset the pending key
+ mPendingWakeKey = PENDING_KEY_NULL;
+ }
+ } else if (!interactive && shouldDispatchInputWhenNonInteractive(event)) {
// If we're currently dozing with the screen on and the keyguard showing, pass the key
// to the application but preserve its wake key status to make sure we still move
// from dozing to fully interactive if we would normally go from off to fully
// interactive.
result = ACTION_PASS_TO_USER;
+ // Since we're dispatching the input, reset the pending key
+ mPendingWakeKey = PENDING_KEY_NULL;
} else {
// When the screen is off and the key is not injected, determine whether
// to wake the device but don't pass the key to the application.
@@ -5573,6 +5592,10 @@ public class PhoneWindowManager implements WindowManagerPolicy {
if (isWakeKey && (!down || !isWakeKeyWhenScreenOff(keyCode))) {
isWakeKey = false;
}
+ // Cache the wake key on down event so we can also avoid sending the up event to the app
+ if (isWakeKey && down) {
+ mPendingWakeKey = keyCode;
+ }
}
// If the key would be handled globally, just return the result, don't worry about special
@@ -5949,7 +5972,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
}
- if (shouldDispatchInputWhenNonInteractive()) {
+ if (shouldDispatchInputWhenNonInteractive(null)) {
return ACTION_PASS_TO_USER;
}
@@ -5964,7 +5987,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
return 0;
}
- private boolean shouldDispatchInputWhenNonInteractive() {
+ private boolean shouldDispatchInputWhenNonInteractive(KeyEvent event) {
final boolean displayOff = (mDisplay == null || mDisplay.getState() == Display.STATE_OFF);
if (displayOff && !mHasFeatureWatch) {
@@ -5976,6 +5999,14 @@ public class PhoneWindowManager implements WindowManagerPolicy {
return true;
}
+ // Watches handle BACK specially
+ if (mHasFeatureWatch
+ && event != null
+ && (event.getKeyCode() == KeyEvent.KEYCODE_BACK
+ || event.getKeyCode() == KeyEvent.KEYCODE_STEM_PRIMARY)) {
+ return false;
+ }
+
// Send events to a dozing dream even if the screen is off since the dream
// is in control of the state of the screen.
IDreamManager dreamManager = getDreamManager();
@@ -7560,7 +7591,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
if (win != null && oldImmersiveMode != newImmersiveMode) {
final String pkg = win.getOwningPackage();
mImmersiveModeConfirmation.immersiveModeChangedLw(pkg, newImmersiveMode,
- isUserSetupComplete());
+ isUserSetupComplete(), isNavBarEmpty(win.getSystemUiVisibility()));
}
vis = mNavigationBarController.updateVisibilityLw(transientNavBarAllowed, oldVis, vis);
@@ -7619,6 +7650,14 @@ public class PhoneWindowManager implements WindowManagerPolicy {
&& canHideNavigationBar();
}
+ private static boolean isNavBarEmpty(int systemUiFlags) {
+ final int disableNavigationBar = (View.STATUS_BAR_DISABLE_HOME
+ | View.STATUS_BAR_DISABLE_BACK
+ | View.STATUS_BAR_DISABLE_RECENT);
+
+ return (systemUiFlags & disableNavigationBar) == disableNavigationBar;
+ }
+
/**
* @return whether the navigation or status bar can be made translucent
*
diff --git a/services/core/java/com/android/server/vr/EnabledComponentsObserver.java b/services/core/java/com/android/server/vr/EnabledComponentsObserver.java
index 77e8b1fa541f..40ee5d88fc8a 100644
--- a/services/core/java/com/android/server/vr/EnabledComponentsObserver.java
+++ b/services/core/java/com/android/server/vr/EnabledComponentsObserver.java
@@ -246,7 +246,9 @@ public class EnabledComponentsObserver implements SettingChangeListener {
Intent queryIntent = new Intent(serviceName);
List<ResolveInfo> installedServices = pm.queryIntentServicesAsUser(
queryIntent,
- PackageManager.GET_SERVICES | PackageManager.GET_META_DATA,
+ PackageManager.GET_SERVICES | PackageManager.GET_META_DATA |
+ PackageManager.MATCH_DIRECT_BOOT_AWARE |
+ PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
userId);
if (installedServices != null) {
for (int i = 0, count = installedServices.size(); i < count; i++) {
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index 06e5e7318d51..4b58a3b6a7aa 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -85,6 +85,7 @@ import android.view.WindowManager;
import com.android.internal.R;
import com.android.internal.content.PackageMonitor;
+import com.android.internal.os.BackgroundThread;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.JournaledFile;
import com.android.server.EventLogTags;
@@ -166,7 +167,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub {
* Observes the wallpaper for changes and notifies all IWallpaperServiceCallbacks
* that the wallpaper has changed. The CREATE is triggered when there is no
* wallpaper set and is created for the first time. The CLOSE_WRITE is triggered
- * everytime the wallpaper is changed.
+ * every time the wallpaper is changed.
*/
private class WallpaperObserver extends FileObserver {
@@ -175,7 +176,6 @@ public class WallpaperManagerService extends IWallpaperManager.Stub {
final File mWallpaperDir;
final File mWallpaperFile;
final File mWallpaperLockFile;
- final File mWallpaperInfoFile;
public WallpaperObserver(WallpaperData wallpaper) {
super(getWallpaperDir(wallpaper.userId).getAbsolutePath(),
@@ -185,7 +185,6 @@ public class WallpaperManagerService extends IWallpaperManager.Stub {
mWallpaper = wallpaper;
mWallpaperFile = new File(mWallpaperDir, WALLPAPER);
mWallpaperLockFile = new File(mWallpaperDir, WALLPAPER_LOCK_ORIG);
- mWallpaperInfoFile = new File(mWallpaperDir, WALLPAPER_INFO);
}
private WallpaperData dataForEvent(boolean sysChanged, boolean lockChanged) {
@@ -943,10 +942,28 @@ public class WallpaperManagerService extends IWallpaperManager.Stub {
mLockWallpaperMap.remove(userId);
}
- void onUnlockUser(int userId) {
+ void onUnlockUser(final int userId) {
synchronized (mLock) {
if (mCurrentUserId == userId && mWaitingForUnlock) {
switchUser(userId, null);
+
+ // Make sure that the SELinux labeling of all the relevant files is correct.
+ // This corrects for mislabeling bugs that might have arisen from move-to
+ // operations involving the wallpaper files. This isn't timing-critical,
+ // so we do it in the background to avoid holding up the user unlock operation.
+ Runnable relabeler = new Runnable() {
+ @Override
+ public void run() {
+ final File wallpaperDir = getWallpaperDir(userId);
+ for (String filename : sPerUserFiles) {
+ File f = new File(wallpaperDir, filename);
+ if (f.exists()) {
+ SELinux.restorecon(f);
+ }
+ }
+ }
+ };
+ BackgroundThread.getHandler().post(relabeler);
}
}
}
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index 2b581562d680..3aefc08746bc 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -604,7 +604,7 @@ public class AppTransition implements Dump {
float scaleH = mTmpRect.height() / (float) appHeight;
Animation scale = new ScaleAnimation(scaleW, 1, scaleH, 1,
computePivot(mTmpRect.left, scaleW),
- computePivot(mTmpRect.right, scaleH));
+ computePivot(mTmpRect.top, scaleH));
scale.setInterpolator(mDecelerateInterpolator);
Animation alpha = new AlphaAnimation(0, 1);
@@ -1615,8 +1615,7 @@ public class AppTransition implements Dump {
if (isTransitionSet()) {
clear();
mNextAppTransitionType = NEXT_TRANSIT_TYPE_SCALE_UP;
- putDefaultNextAppTransitionCoordinates(startX, startY, startX + startWidth,
- startY + startHeight, null);
+ putDefaultNextAppTransitionCoordinates(startX, startY, startWidth, startHeight, null);
postAnimationCallback();
}
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 4c79149f64d3..84788cfda4da 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -545,7 +545,7 @@ public class WindowManagerService extends IWindowManager.Stub
SparseArray<DisplayContent> mDisplayContents = new SparseArray<>(2);
int mRotation = 0;
- int mForcedAppOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
+ int mLastOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
boolean mAltOrientation = false;
private boolean mKeyguardWaitingForActivityDrawn;
@@ -3521,13 +3521,16 @@ public class WindowManagerService extends IWindowManager.Stub
// can re-appear and inflict its own orientation on us. Keep the
// orientation stable until this all settles down.
return mLastWindowForcedOrientation;
- } else if (mPolicy.isKeyguardLocked()
- && mLastKeyguardForcedOrientation != SCREEN_ORIENTATION_UNSPECIFIED) {
- // Use the last orientation the keyguard forced while the display is frozen with the
- // keyguard locked.
+ } else if (mPolicy.isKeyguardLocked()) {
+ // Use the last orientation the while the display is frozen with the
+ // keyguard locked. This could be the keyguard forced orientation or
+ // from a SHOW_WHEN_LOCKED window. We don't want to check the show when
+ // locked window directly though as things aren't stable while
+ // the display is frozen, for example the window could be momentarily unavailable
+ // due to activity relaunch.
if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Display is frozen while keyguard locked, "
- + "return " + mLastKeyguardForcedOrientation);
- return mLastKeyguardForcedOrientation;
+ + "return " + mLastOrientation);
+ return mLastOrientation;
}
} else {
// TODO(multidisplay): Change to the correct display.
@@ -3657,12 +3660,12 @@ public class WindowManagerService extends IWindowManager.Stub
}
}
if (DEBUG_ORIENTATION) Slog.v(TAG_WM,
- "No app is requesting an orientation, return " + mForcedAppOrientation);
+ "No app is requesting an orientation, return " + mLastOrientation);
// The next app has not been requested to be visible, so we keep the current orientation
// to prevent freezing/unfreezing the display too early unless we are in multi-window, in
// which we don't let the app customize the orientation unless it was the home task that
// is handled above.
- return inMultiWindow ? SCREEN_ORIENTATION_UNSPECIFIED : mForcedAppOrientation;
+ return inMultiWindow ? SCREEN_ORIENTATION_UNSPECIFIED : mLastOrientation;
}
@Override
@@ -3745,8 +3748,8 @@ public class WindowManagerService extends IWindowManager.Stub
long ident = Binder.clearCallingIdentity();
try {
int req = getOrientationLocked();
- if (req != mForcedAppOrientation) {
- mForcedAppOrientation = req;
+ if (req != mLastOrientation) {
+ mLastOrientation = req;
//send a message to Policy indicating orientation change to take
//action like disabling/enabling sensors etc.,
mPolicy.setCurrentOrientationLw(req);
@@ -6159,6 +6162,21 @@ public class WindowManagerService extends IWindowManager.Stub
}
}
+ @Override
+ public Bitmap screenshotWallpaper() {
+ if (!checkCallingPermission(Manifest.permission.READ_FRAME_BUFFER,
+ "screenshotWallpaper()")) {
+ throw new SecurityException("Requires READ_FRAME_BUFFER permission");
+ }
+ try {
+ Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "screenshotWallpaper");
+ return screenshotApplicationsInner(null, Display.DEFAULT_DISPLAY, -1, -1, true, 1f,
+ Bitmap.Config.ARGB_8888, true);
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
+ }
+ }
+
/**
* Takes a snapshot of the screen. In landscape mode this grabs the whole screen.
* In portrait mode, it grabs the upper region of the screen based on the vertical dimension
@@ -6175,7 +6193,7 @@ public class WindowManagerService extends IWindowManager.Stub
@Override
public void run() {
Bitmap bm = screenshotApplicationsInner(null, Display.DEFAULT_DISPLAY, -1, -1,
- true, 1f, Bitmap.Config.ARGB_8888);
+ true, 1f, Bitmap.Config.ARGB_8888, false);
try {
receiver.send(bm);
} catch (RemoteException e) {
@@ -6205,14 +6223,27 @@ public class WindowManagerService extends IWindowManager.Stub
try {
Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "screenshotApplications");
return screenshotApplicationsInner(appToken, displayId, width, height, false,
- frameScale, Bitmap.Config.RGB_565);
+ frameScale, Bitmap.Config.RGB_565, false);
} finally {
Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
}
}
+ /**
+ * Takes a snapshot of the screen. In landscape mode this grabs the whole screen.
+ * In portrait mode, it grabs the full screenshot.
+ *
+ * @param displayId the Display to take a screenshot of.
+ * @param width the width of the target bitmap
+ * @param height the height of the target bitmap
+ * @param includeFullDisplay true if the screen should not be cropped before capture
+ * @param frameScale the scale to apply to the frame, only used when width = -1 and height = -1
+ * @param config of the output bitmap
+ * @param wallpaperOnly true if only the wallpaper layer should be included in the screenshot
+ */
Bitmap screenshotApplicationsInner(IBinder appToken, int displayId, int width, int height,
- boolean includeFullDisplay, float frameScale, Bitmap.Config config) {
+ boolean includeFullDisplay, float frameScale, Bitmap.Config config,
+ boolean wallpaperOnly) {
final DisplayContent displayContent;
synchronized(mWindowMap) {
displayContent = getDisplayContentLocked(displayId);
@@ -6239,7 +6270,7 @@ public class WindowManagerService extends IWindowManager.Stub
boolean screenshotReady;
int minLayer;
- if (appToken == null) {
+ if (appToken == null && !wallpaperOnly) {
screenshotReady = true;
minLayer = 0;
} else {
@@ -6279,11 +6310,20 @@ public class WindowManagerService extends IWindowManager.Stub
if (ws.mLayer >= aboveAppLayer) {
continue;
}
+ if (wallpaperOnly && !ws.mIsWallpaper) {
+ continue;
+ }
if (ws.mIsImWindow) {
if (!includeImeInScreenshot) {
continue;
}
} else if (ws.mIsWallpaper) {
+ // If this is the wallpaper layer and we're only looking for the wallpaper layer
+ // then the target window state is this one.
+ if (wallpaperOnly) {
+ appWin = ws;
+ }
+
if (appWin == null) {
// We have not ran across the target window yet, so it is probably
// behind the wallpaper. This can happen when the keyguard is up and
@@ -6331,8 +6371,10 @@ public class WindowManagerService extends IWindowManager.Stub
}
}
- if (ws.mAppToken != null && ws.mAppToken.token == appToken &&
- ws.isDisplayedLw() && winAnim.getShown()) {
+ final boolean foundTargetWs =
+ (ws.mAppToken != null && ws.mAppToken.token == appToken)
+ || (appWin != null && wallpaperOnly);
+ if (foundTargetWs && ws.isDisplayedLw() && winAnim.getShown()) {
screenshotReady = true;
}
@@ -6622,13 +6664,13 @@ public class WindowManagerService extends IWindowManager.Stub
// an orientation that has different metrics than it expected.
// eg. Portrait instead of Landscape.
- int rotation = mPolicy.rotationForOrientationLw(mForcedAppOrientation, mRotation);
+ int rotation = mPolicy.rotationForOrientationLw(mLastOrientation, mRotation);
boolean altOrientation = !mPolicy.rotationHasCompatibleMetricsLw(
- mForcedAppOrientation, rotation);
+ mLastOrientation, rotation);
if (DEBUG_ORIENTATION) {
- Slog.v(TAG_WM, "Application requested orientation "
- + mForcedAppOrientation + ", got rotation " + rotation
+ Slog.v(TAG_WM, "Selected orientation "
+ + mLastOrientation + ", got rotation " + rotation
+ " which has " + (altOrientation ? "incompatible" : "compatible")
+ " metrics");
}
@@ -6642,7 +6684,7 @@ public class WindowManagerService extends IWindowManager.Stub
Slog.v(TAG_WM,
"Rotation changed to " + rotation + (altOrientation ? " (alt)" : "")
+ " from " + mRotation + (mAltOrientation ? " (alt)" : "")
- + ", forceApp=" + mForcedAppOrientation);
+ + ", lastOrientation=" + mLastOrientation);
}
int oldRotation = mRotation;
@@ -10487,7 +10529,7 @@ public class WindowManagerService extends IWindowManager.Stub
pw.print(" mRotation="); pw.print(mRotation);
pw.print(" mAltOrientation="); pw.println(mAltOrientation);
pw.print(" mLastWindowForcedOrientation="); pw.print(mLastWindowForcedOrientation);
- pw.print(" mForcedAppOrientation="); pw.println(mForcedAppOrientation);
+ pw.print(" mLastOrientation="); pw.println(mLastOrientation);
pw.print(" mDeferredRotationPauseCount="); pw.println(mDeferredRotationPauseCount);
pw.print(" Animation settings: disabled="); pw.print(mAnimationsDisabled);
pw.print(" window="); pw.print(mWindowAnimationScaleSetting);
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 31b756e57037..2120be1ec531 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -218,6 +218,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
private static final String ATTR_SETUP_COMPLETE = "setup-complete";
private static final String ATTR_PROVISIONING_STATE = "provisioning-state";
private static final String ATTR_PERMISSION_POLICY = "permission-policy";
+ private static final String ATTR_DEVICE_PROVISIONING_CONFIG_APPLIED =
+ "device-provisioning-config-applied";
private static final String ATTR_DELEGATED_CERT_INSTALLER = "delegated-cert-installer";
private static final String ATTR_APPLICATION_RESTRICTIONS_MANAGER
@@ -417,6 +419,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
int mUserProvisioningState;
int mPermissionPolicy;
+ boolean mDeviceProvisioningConfigApplied = false;
+
final ArrayMap<ComponentName, ActiveAdmin> mAdminMap = new ArrayMap<>();
final ArrayList<ActiveAdmin> mAdminList = new ArrayList<>();
final ArrayList<ComponentName> mRemovingAdmins = new ArrayList<>();
@@ -2173,6 +2177,10 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
out.attribute(null, ATTR_SETUP_COMPLETE,
Boolean.toString(true));
}
+ if (policy.mDeviceProvisioningConfigApplied) {
+ out.attribute(null, ATTR_DEVICE_PROVISIONING_CONFIG_APPLIED,
+ Boolean.toString(true));
+ }
if (policy.mUserProvisioningState != DevicePolicyManager.STATE_USER_UNMANAGED) {
out.attribute(null, ATTR_PROVISIONING_STATE,
Integer.toString(policy.mUserProvisioningState));
@@ -2333,6 +2341,12 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
if (userSetupComplete != null && Boolean.toString(true).equals(userSetupComplete)) {
policy.mUserSetupComplete = true;
}
+ String deviceProvisioningConfigApplied = parser.getAttributeValue(null,
+ ATTR_DEVICE_PROVISIONING_CONFIG_APPLIED);
+ if (deviceProvisioningConfigApplied != null
+ && Boolean.toString(true).equals(deviceProvisioningConfigApplied)) {
+ policy.mDeviceProvisioningConfigApplied = true;
+ }
String provisioningState = parser.getAttributeValue(null, ATTR_PROVISIONING_STATE);
if (!TextUtils.isEmpty(provisioningState)) {
policy.mUserProvisioningState = Integer.parseInt(provisioningState);
@@ -9046,4 +9060,23 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
// restrictions.
pushUserRestrictions(userHandle);
}
+
+ @Override
+ public void setDeviceProvisioningConfigApplied() {
+ enforceManageUsers();
+ synchronized (this) {
+ DevicePolicyData policy = getUserData(UserHandle.USER_SYSTEM);
+ policy.mDeviceProvisioningConfigApplied = true;
+ saveSettingsLocked(UserHandle.USER_SYSTEM);
+ }
+ }
+
+ @Override
+ public boolean isDeviceProvisioningConfigApplied() {
+ enforceManageUsers();
+ synchronized (this) {
+ final DevicePolicyData policy = getUserData(UserHandle.USER_SYSTEM);
+ return policy.mDeviceProvisioningConfigApplied;
+ }
+ }
}
diff --git a/services/retaildemo/java/com/android/server/retaildemo/RetailDemoModeService.java b/services/retaildemo/java/com/android/server/retaildemo/RetailDemoModeService.java
index 855a2b6d9253..c351e738a04f 100644
--- a/services/retaildemo/java/com/android/server/retaildemo/RetailDemoModeService.java
+++ b/services/retaildemo/java/com/android/server/retaildemo/RetailDemoModeService.java
@@ -321,13 +321,15 @@ public class RetailDemoModeService extends SystemService {
private void setupDemoUser(UserInfo userInfo) {
UserManager um = getUserManager();
UserHandle user = UserHandle.of(userInfo.id);
- LockPatternUtils lockPatternUtils = new LockPatternUtils(getContext());
- lockPatternUtils.setLockScreenDisabled(true, userInfo.id);
um.setUserRestriction(UserManager.DISALLOW_CONFIG_WIFI, true, user);
um.setUserRestriction(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES, true, user);
um.setUserRestriction(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS, true, user);
um.setUserRestriction(UserManager.DISALLOW_USB_FILE_TRANSFER, true, user);
um.setUserRestriction(UserManager.DISALLOW_MODIFY_ACCOUNTS, true, user);
+ um.setUserRestriction(UserManager.DISALLOW_CONFIG_BLUETOOTH, true, user);
+ // Disallow rebooting in safe mode - controlled by user 0
+ getUserManager().setUserRestriction(UserManager.DISALLOW_SAFE_BOOT, true,
+ UserHandle.SYSTEM);
Settings.Secure.putIntForUser(getContext().getContentResolver(),
Settings.Secure.SKIP_FIRST_USE_HINTS, 1, userInfo.id);
Settings.Secure.putIntForUser(getContext().getContentResolver(),
@@ -496,6 +498,9 @@ public class RetailDemoModeService extends SystemService {
mAmi.updatePersistentConfigurationForUser(getSystemUsersConfiguration(), userId);
turnOffAllFlashLights();
muteVolumeStreams();
+ // Disable lock screen for demo users.
+ LockPatternUtils lockPatternUtils = new LockPatternUtils(getContext());
+ lockPatternUtils.setLockScreenDisabled(true, userId);
mNm.notifyAsUser(TAG, 1, createResetNotification(), UserHandle.of(userId));
synchronized (mActivityLock) {
diff --git a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
index 3d68b591c26f..1be57bccbdb7 100644
--- a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
@@ -404,11 +404,6 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
// During tests, WTF is fatal.
fail(message + " exception: " + th + "\n" + Log.getStackTraceString(th));
}
-
- @Override
- boolean injectCheckPendingTaskWaitThread() {
- return true;
- }
}
/** ShortcutManager with injection override methods. */
@@ -853,8 +848,6 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
protected void shutdownServices() {
if (mService != null) {
- mService.getPendingTasksForTest().waitOnAllTasks();
-
// Flush all the unsaved data from the previous instance.
mService.saveDirtyInfo();
@@ -1480,12 +1473,30 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
return new File(si.getBitmapPath()).getName();
}
+ /**
+ * @return all shortcuts stored internally for the caller. This reflects the *internal* view
+ * of shortcuts, which may be different from what {@link #getCallerVisibleShortcuts} would
+ * return, because getCallerVisibleShortcuts() will get shortcuts from the proper "front door"
+ * which performs some extra checks, like {@link ShortcutPackage#onRestored}.
+ */
protected List<ShortcutInfo> getCallerShortcuts() {
final ShortcutPackage p = mService.getPackageShortcutForTest(
getCallingPackage(), getCallingUserId());
return p == null ? null : p.getAllShortcutsForTest();
}
+ /**
+ * @return all shortcuts owned by caller that are actually visible via ShortcutManager.
+ * See also {@link #getCallerShortcuts}.
+ */
+ protected List<ShortcutInfo> getCallerVisibleShortcuts() {
+ final ArrayList<ShortcutInfo> ret = new ArrayList<>();
+ ret.addAll(mManager.getDynamicShortcuts());
+ ret.addAll(mManager.getPinnedShortcuts());
+ ret.addAll(mManager.getManifestShortcuts());
+ return ret;
+ }
+
protected ShortcutInfo getCallerShortcut(String shortcutId) {
return getPackageShortcut(getCallingPackage(), shortcutId, getCallingUserId());
}
@@ -1696,6 +1707,8 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s2", "s5"), HANDLE_USER_P0);
});
+
+ // Note LAUNCHER_3 has allowBackup=false.
runWithCaller(LAUNCHER_3, USER_0, () -> {
mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s3"), HANDLE_USER_0);
mLauncherApps.pinShortcuts(CALLING_PACKAGE_2, list("s3", "s4"), HANDLE_USER_0);
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
index aa1072e14726..bf6c2ff97bec 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
@@ -62,7 +62,6 @@ import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
import android.Manifest.permission;
import android.app.ActivityManager;
@@ -1298,7 +1297,8 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
R.xml.shortcut_3);
updatePackageVersion(CALLING_PACKAGE_1, 1);
- mInternal.onPackageBroadcast(genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
+ mService.mPackageMonitor.onReceive(getTestContext(),
+ genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
assertTrue(mManager.setDynamicShortcuts(list(
@@ -1316,7 +1316,8 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
R.xml.shortcut_2);
updatePackageVersion(CALLING_PACKAGE_1, 1);
- mInternal.onPackageBroadcast(genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
+ mService.mPackageMonitor.onReceive(getTestContext(),
+ genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
assertTrue(mManager.setDynamicShortcuts(list(
@@ -2814,7 +2815,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
R.xml.shortcut_2);
updatePackageVersion(CALLING_PACKAGE_1, 1);
- mInternal.onPackageBroadcast(
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
}).assertCallbackCalledForPackageAndUser(CALLING_PACKAGE_1, HANDLE_USER_0)
.areAllManifest()
@@ -2851,7 +2852,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
R.xml.shortcut_0);
updatePackageVersion(CALLING_PACKAGE_1, 1);
- mInternal.onPackageBroadcast(
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
assertForLauncherCallback(mLauncherApps, () -> {
@@ -3471,7 +3472,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
R.xml.shortcut_2);
updatePackageVersion(CALLING_PACKAGE_1, 1);
- mInternal.onPackageBroadcast(
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
@@ -3488,7 +3489,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
R.xml.shortcut_1);
updatePackageVersion(CALLING_PACKAGE_1, 1);
- mInternal.onPackageBroadcast(
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
@@ -3850,7 +3851,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
R.xml.shortcut_1);
updatePackageVersion(CALLING_PACKAGE_1, 1);
- mInternal.onPackageBroadcast(
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
assertWith(getCallerShortcuts())
@@ -3890,7 +3891,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_3, USER_10));
uninstallPackage(USER_0, CALLING_PACKAGE_1);
- mInternal.onPackageBroadcast(
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageDeleteIntent(CALLING_PACKAGE_1, USER_0));
assertNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "s1", USER_0));
@@ -3910,7 +3911,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
mRunningUsers.put(USER_10, true);
uninstallPackage(USER_10, CALLING_PACKAGE_2);
- mInternal.onPackageBroadcast(
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageDeleteIntent(CALLING_PACKAGE_2, USER_10));
assertNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "s1", USER_0));
@@ -4001,7 +4002,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_2, USER_10));
assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_3, USER_10));
- mInternal.onPackageBroadcast(
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageDataClear(CALLING_PACKAGE_1, USER_0));
assertNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "s1", USER_0));
@@ -4020,7 +4021,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
mRunningUsers.put(USER_10, true);
- mInternal.onPackageBroadcast(
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageDataClear(CALLING_PACKAGE_2, USER_10));
assertNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "s1", USER_0));
@@ -4047,7 +4048,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
R.xml.shortcut_2);
updatePackageVersion(CALLING_PACKAGE_1, 1);
- mInternal.onPackageBroadcast(
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageAddIntent(CALLING_PACKAGE_1, USER_10));
runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
@@ -4068,7 +4069,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
});
// Clear data
- mInternal.onPackageBroadcast(
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageDataClear(CALLING_PACKAGE_1, USER_10));
// Only manifest shortcuts will remain, and are no longer pinned.
@@ -4133,9 +4134,9 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
reset(c0);
reset(c10);
- mInternal.onPackageBroadcast(
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageUpdateIntent(CALLING_PACKAGE_1, USER_0));
- mInternal.onPackageBroadcast(
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageUpdateIntent(CALLING_PACKAGE_1, USER_10));
waitOnMainThread();
@@ -4156,7 +4157,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
updatePackageVersion(CALLING_PACKAGE_1, 1);
// Then send the broadcast, to only user-0.
- mInternal.onPackageBroadcast(
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageUpdateIntent(CALLING_PACKAGE_1, USER_0));
waitOnMainThread();
@@ -4221,7 +4222,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
updatePackageVersion(CALLING_PACKAGE_2, 10);
// Then send the broadcast, to only user-0.
- mInternal.onPackageBroadcast(
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageUpdateIntent(CALLING_PACKAGE_2, USER_0));
mService.handleUnlockUser(USER_10);
@@ -4245,7 +4246,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
updatePackageVersion(CALLING_PACKAGE_3, 100);
// Then send the broadcast, to only user-0.
- mInternal.onPackageBroadcast(
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageUpdateIntent(CALLING_PACKAGE_3, USER_0));
mService.handleUnlockUser(USER_10);
@@ -4327,7 +4328,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
// Update the package.
updatePackageVersion(CALLING_PACKAGE_1, 1);
- mInternal.onPackageBroadcast(
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageUpdateIntent(CALLING_PACKAGE_1, USER_0));
runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
@@ -4356,7 +4357,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
mRunningUsers.put(USER_10, true);
updatePackageVersion(CALLING_PACKAGE_1, 1);
- mInternal.onPackageBroadcast(
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageAddIntent(CALLING_PACKAGE_1, USER_10));
runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
@@ -4388,7 +4389,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
});
// First, no changes.
- mInternal.onPackageBroadcast(
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageChangedIntent(CALLING_PACKAGE_1, USER_10));
runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
@@ -4411,7 +4412,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
// Disable activity 1
mEnabledActivityChecker = (activity, userId) -> !ACTIVITY1.equals(activity);
- mInternal.onPackageBroadcast(
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageChangedIntent(CALLING_PACKAGE_1, USER_10));
runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
@@ -4431,7 +4432,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
// Re-enable activity 1.
// Manifest shortcuts will be re-published, but dynamic ones are not.
mEnabledActivityChecker = (activity, userId) -> true;
- mInternal.onPackageBroadcast(
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageChangedIntent(CALLING_PACKAGE_1, USER_10));
runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
@@ -4455,7 +4456,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
// Disable activity 2
// Because "ms1-alt" and "s2" are both pinned, they will remain, but disabled.
mEnabledActivityChecker = (activity, userId) -> !ACTIVITY2.equals(activity);
- mInternal.onPackageBroadcast(
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageChangedIntent(CALLING_PACKAGE_1, USER_10));
runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
@@ -4518,7 +4519,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
setCaller(LAUNCHER_1, USER_0);
assertForLauncherCallback(mLauncherApps, () -> {
updatePackageVersion(CALLING_PACKAGE_1, 1);
- mInternal.onPackageBroadcast(
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageUpdateIntent(CALLING_PACKAGE_1, USER_0));
}).assertCallbackCalledForPackageAndUser(CALLING_PACKAGE_1, HANDLE_USER_0)
// Make sure the launcher gets callbacks.
@@ -4635,8 +4636,10 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
final ShortcutUser user0 = mService.getUserShortcutsLocked(USER_0);
assertExistsAndShadow(user0.getAllPackagesForTest().get(CALLING_PACKAGE_1));
assertExistsAndShadow(user0.getAllPackagesForTest().get(CALLING_PACKAGE_2));
- assertExistsAndShadow(user0.getAllLaunchersForTest().get(PackageWithUser.of(USER_0, LAUNCHER_1)));
- assertExistsAndShadow(user0.getAllLaunchersForTest().get(PackageWithUser.of(USER_0, LAUNCHER_2)));
+ assertExistsAndShadow(user0.getAllLaunchersForTest().get(
+ PackageWithUser.of(USER_0, LAUNCHER_1)));
+ assertExistsAndShadow(user0.getAllLaunchersForTest().get(
+ PackageWithUser.of(USER_0, LAUNCHER_2)));
assertNull(user0.getAllPackagesForTest().get(CALLING_PACKAGE_3));
assertNull(user0.getAllLaunchersForTest().get(PackageWithUser.of(USER_0, LAUNCHER_3)));
@@ -4644,90 +4647,98 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
installPackage(USER_0, CALLING_PACKAGE_1);
runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
- assertEquals(0, mManager.getDynamicShortcuts().size());
- assertShortcutIds(assertAllPinned(
- mManager.getPinnedShortcuts()),
- "s1", "s2");
+ assertWith(getCallerVisibleShortcuts())
+ .selectDynamic()
+ .isEmpty()
+
+ .revertToOriginalList()
+ .selectPinned()
+ .haveIds("s1", "s2");
});
installPackage(USER_0, LAUNCHER_1);
runWithCaller(LAUNCHER_1, USER_0, () -> {
- assertShortcutIds(assertAllPinned(
- mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_0)),
- "s1");
- assertShortcutIds(assertAllPinned(
- mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_0))
- /* empty, not restored */ );
- assertShortcutIds(assertAllPinned(
- mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_0))
- /* empty, not restored */ );
+ assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_0))
+ .areAllPinned()
+ .haveIds("s1");
+
+ assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_0))
+ .isEmpty();
+
+ assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_0))
+ .isEmpty();
- assertEquals(0, mLauncherApps.getShortcuts(QUERY_ALL, HANDLE_USER_P0).size());
+ assertWith(mLauncherApps.getShortcuts(QUERY_ALL, HANDLE_USER_P0))
+ .isEmpty();
});
installPackage(USER_0, CALLING_PACKAGE_2);
runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
- assertEquals(0, mManager.getDynamicShortcuts().size());
- assertShortcutIds(assertAllPinned(
- mManager.getPinnedShortcuts()),
- "s1", "s2", "s3");
+ assertWith(getCallerVisibleShortcuts())
+ .selectDynamic()
+ .isEmpty()
+
+ .revertToOriginalList()
+ .selectPinned()
+ .haveIds("s1", "s2", "s3");
});
runWithCaller(LAUNCHER_1, USER_0, () -> {
- assertShortcutIds(assertAllPinned(
- mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_0)),
- "s1");
- assertShortcutIds(assertAllPinned(
- mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_0)),
- "s1", "s2");
- assertShortcutIds(assertAllPinned(
- mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_0))
- /* empty, not restored */ );
+ assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_0))
+ .areAllPinned()
+ .haveIds("s1");
+
+ assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_0))
+ .areAllPinned()
+ .haveIds("s1", "s2");
+
+ assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_0))
+ .isEmpty();
- assertEquals(0, mLauncherApps.getShortcuts(QUERY_ALL, HANDLE_USER_P0).size());
+ assertWith(mLauncherApps.getShortcuts(QUERY_ALL, HANDLE_USER_P0))
+ .isEmpty();
});
// 3 shouldn't be backed up, so no pinned shortcuts.
installPackage(USER_0, CALLING_PACKAGE_3);
runWithCaller(CALLING_PACKAGE_3, USER_0, () -> {
- assertEquals(0, mManager.getDynamicShortcuts().size());
- assertEquals(0, mManager.getPinnedShortcuts().size());
+ assertWith(getCallerVisibleShortcuts())
+ .isEmpty();
});
// Launcher on a different profile shouldn't be restored.
runWithCaller(LAUNCHER_1, USER_P0, () -> {
- assertEquals(0,
- mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_0)
- .size());
- assertEquals(0,
- mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_0)
- .size());
- assertShortcutIds(assertAllPinned(
- mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_0))
- /* wasn't restored, so still empty */ );
+ assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_0))
+ .isEmpty();
+ assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_0))
+ .isEmpty();
+ assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_0))
+ .isEmpty();
});
// Package on a different profile, no restore.
installPackage(USER_P0, CALLING_PACKAGE_1);
runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
- assertEquals(0, mManager.getDynamicShortcuts().size());
- assertEquals(0, mManager.getPinnedShortcuts().size());
+ assertWith(getCallerVisibleShortcuts())
+ .isEmpty();
});
// Restore launcher 2 on user 0.
installPackage(USER_0, LAUNCHER_2);
runWithCaller(LAUNCHER_2, USER_0, () -> {
- assertShortcutIds(assertAllPinned(
- mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_0)),
- "s2");
- assertShortcutIds(assertAllPinned(
- mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_0)),
- "s2", "s3");
- assertShortcutIds(assertAllPinned(
- mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_0))
- /* wasn't restored, so still empty */ );
+ assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_0))
+ .areAllPinned()
+ .haveIds("s2");
+
+ assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_0))
+ .areAllPinned()
+ .haveIds("s2", "s3");
+
+ assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_0))
+ .isEmpty();
- assertEquals(0, mLauncherApps.getShortcuts(QUERY_ALL, HANDLE_USER_P0).size());
+ assertWith(mLauncherApps.getShortcuts(QUERY_ALL, HANDLE_USER_P0))
+ .isEmpty();
});
@@ -4735,33 +4746,33 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
// make sure they still have the same result.
installPackage(USER_0, CALLING_PACKAGE_1);
runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
- assertEquals(0, mManager.getDynamicShortcuts().size());
- assertShortcutIds(assertAllPinned(
- mManager.getPinnedShortcuts()),
- "s1", "s2");
+ assertWith(getCallerVisibleShortcuts())
+ .areAllPinned()
+ .haveIds("s1", "s2");
});
installPackage(USER_0, LAUNCHER_1);
runWithCaller(LAUNCHER_1, USER_0, () -> {
- assertShortcutIds(assertAllPinned(
- mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_0)),
- "s1");
- assertShortcutIds(assertAllPinned(
- mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_0)),
- "s1", "s2");
- assertShortcutIds(assertAllPinned(
- mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_0))
- /* wasn't restored, so still empty */ );
+ assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_0))
+ .areAllPinned()
+ .haveIds("s1");
+
+ assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_0))
+ .areAllPinned()
+ .haveIds("s1", "s2");
+
+ assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_0))
+ .isEmpty();
- assertEquals(0, mLauncherApps.getShortcuts(QUERY_ALL, HANDLE_USER_P0).size());
+ assertWith(mLauncherApps.getShortcuts(QUERY_ALL, HANDLE_USER_P0))
+ .isEmpty();
});
installPackage(USER_0, CALLING_PACKAGE_2);
runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
- assertEquals(0, mManager.getDynamicShortcuts().size());
- assertShortcutIds(assertAllPinned(
- mManager.getPinnedShortcuts()),
- "s1", "s2", "s3");
+ assertWith(getCallerVisibleShortcuts())
+ .areAllPinned()
+ .haveIds("s1", "s2", "s3");
});
}
@@ -5082,6 +5093,112 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
});
}
+ public void testBackupAndRestore_disabled() {
+ prepareCrossProfileDataSet();
+
+ // Before doing backup & restore, disable s1.
+ runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+ mManager.disableShortcuts(list("s1"));
+ });
+
+ backupAndRestore();
+
+ // Below is copied from checkBackupAndRestore_success.
+
+ // Make sure non-system user is not restored.
+ final ShortcutUser userP0 = mService.getUserShortcutsLocked(USER_P0);
+ assertEquals(0, userP0.getAllPackagesForTest().size());
+ assertEquals(0, userP0.getAllLaunchersForTest().size());
+
+ // Make sure only "allowBackup" apps are restored, and are shadow.
+ final ShortcutUser user0 = mService.getUserShortcutsLocked(USER_0);
+ assertExistsAndShadow(user0.getAllPackagesForTest().get(CALLING_PACKAGE_1));
+ assertExistsAndShadow(user0.getAllPackagesForTest().get(CALLING_PACKAGE_2));
+ assertExistsAndShadow(user0.getAllLaunchersForTest().get(
+ PackageWithUser.of(USER_0, LAUNCHER_1)));
+ assertExistsAndShadow(user0.getAllLaunchersForTest().get(
+ PackageWithUser.of(USER_0, LAUNCHER_2)));
+
+ assertNull(user0.getAllPackagesForTest().get(CALLING_PACKAGE_3));
+ assertNull(user0.getAllLaunchersForTest().get(PackageWithUser.of(USER_0, LAUNCHER_3)));
+ assertNull(user0.getAllLaunchersForTest().get(PackageWithUser.of(USER_P0, LAUNCHER_1)));
+
+ installPackage(USER_0, CALLING_PACKAGE_1);
+ runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+ assertWith(getCallerVisibleShortcuts())
+ .areAllEnabled() // disabled shortcuts shouldn't be restored.
+
+ .selectDynamic()
+ .isEmpty()
+
+ .revertToOriginalList()
+ .selectPinned()
+ // s1 is not restored.
+ .haveIds("s2");
+ });
+
+ installPackage(USER_0, LAUNCHER_1);
+ runWithCaller(LAUNCHER_1, USER_0, () -> {
+ // Note, s1 was pinned by launcher 1, but was disabled, so isn't restored.
+ assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_0))
+ .isEmpty();
+
+ assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_0))
+ .isEmpty();
+
+ assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_0))
+ .isEmpty();
+
+ assertWith(mLauncherApps.getShortcuts(QUERY_ALL, HANDLE_USER_P0))
+ .isEmpty();
+ });
+ }
+
+
+ public void testBackupAndRestore_manifestNotRestored() {
+ // Publish two manifest shortcuts.
+ addManifestShortcutResource(
+ new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
+ R.xml.shortcut_2);
+ updatePackageVersion(CALLING_PACKAGE_1, 1);
+ mService.mPackageMonitor.onReceive(mServiceContext,
+ genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
+
+ // Pin from launcher 1.
+ runWithCaller(LAUNCHER_1, USER_0, () -> {
+ mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("ms1", "ms2"), HANDLE_USER_0);
+ });
+
+ // Update and now ms2 is gone -> disabled.
+ addManifestShortcutResource(
+ new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
+ R.xml.shortcut_1);
+ updatePackageVersion(CALLING_PACKAGE_1, 1);
+ mService.mPackageMonitor.onReceive(mServiceContext,
+ genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
+
+ // Make sure the manifest shortcuts have been published.
+ runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+ assertWith(getCallerShortcuts())
+ .areAllPinned()
+ .haveIds("ms1", "ms2")
+
+ .selectByIds("ms1")
+ .areAllManifest()
+ .areAllEnabled()
+
+ .revertToOriginalList()
+ .selectByIds("ms2")
+ .areAllNotManifest()
+ .areAllDisabled();
+ });
+
+ // Now do the regular backup & restore test.
+ // The existence of the manifest shortcuts shouldn't affect the result.
+ prepareCrossProfileDataSet();
+ backupAndRestore();
+ }
+
public void testSaveAndLoad_crossProfile() {
prepareCrossProfileDataSet();
@@ -5518,7 +5635,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
R.xml.shortcut_1);
updatePackageVersion(CALLING_PACKAGE_1, 1);
- mInternal.onPackageBroadcast(
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
@@ -5539,7 +5656,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
new ComponentName(CALLING_PACKAGE_2, ShortcutActivity.class.getName()),
R.xml.shortcut_5);
updatePackageVersion(CALLING_PACKAGE_2, 1);
- mInternal.onPackageBroadcast(
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageAddIntent(CALLING_PACKAGE_2, USER_0));
runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
@@ -5576,7 +5693,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
new ComponentName(CALLING_PACKAGE_2, ShortcutActivity.class.getName()),
R.xml.shortcut_2);
updatePackageLastUpdateTime(CALLING_PACKAGE_2, 1);
- mInternal.onPackageBroadcast(
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageAddIntent(CALLING_PACKAGE_2, USER_0));
runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
@@ -5613,7 +5730,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
mRunningUsers.put(USER_10, false);
mUnlockedUsers.put(USER_10, false);
- mInternal.onPackageBroadcast(
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageAddIntent(CALLING_PACKAGE_2, USER_10));
runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
assertEmpty(mManager.getManifestShortcuts());
@@ -5623,7 +5740,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
// Try again, but the user is locked, so still ignored.
mRunningUsers.put(USER_10, true);
- mInternal.onPackageBroadcast(
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageAddIntent(CALLING_PACKAGE_2, USER_10));
runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
assertEmpty(mManager.getManifestShortcuts());
@@ -5634,7 +5751,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
mUnlockedUsers.put(USER_10, true);
// Send PACKAGE_ADD broadcast to have Package 2 on user-10 publish manifest shortcuts.
- mInternal.onPackageBroadcast(
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageAddIntent(CALLING_PACKAGE_2, USER_10));
runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
@@ -5675,7 +5792,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
R.xml.shortcut_5_reverse);
updatePackageLastUpdateTime(CALLING_PACKAGE_2, 1);
- mInternal.onPackageBroadcast(
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageAddIntent(CALLING_PACKAGE_2, USER_0));
runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
@@ -5703,7 +5820,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
new ComponentName(CALLING_PACKAGE_2, ShortcutActivity2.class.getName()),
R.xml.shortcut_0);
updatePackageLastUpdateTime(CALLING_PACKAGE_2, 1);
- mInternal.onPackageBroadcast(
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageAddIntent(CALLING_PACKAGE_2, USER_0));
// No manifest shortcuts, and pinned ones are disabled.
@@ -5734,7 +5851,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
R.xml.shortcut_error_1);
updatePackageVersion(CALLING_PACKAGE_1, 1);
- mInternal.onPackageBroadcast(
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
// Only the valid one is published.
@@ -5749,7 +5866,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
R.xml.shortcut_error_2);
updatePackageVersion(CALLING_PACKAGE_1, 1);
- mInternal.onPackageBroadcast(
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
// Only the valid one is published.
@@ -5764,7 +5881,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
R.xml.shortcut_error_3);
updatePackageVersion(CALLING_PACKAGE_1, 1);
- mInternal.onPackageBroadcast(
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
// Only the valid one is published.
@@ -5780,7 +5897,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
R.xml.shortcut_error_4);
updatePackageVersion(CALLING_PACKAGE_1, 1);
- mInternal.onPackageBroadcast(
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
@@ -5808,7 +5925,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
R.xml.shortcut_5);
updatePackageVersion(CALLING_PACKAGE_1, 1);
- mInternal.onPackageBroadcast(
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
@@ -5846,7 +5963,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
R.xml.shortcut_error_4);
updatePackageVersion(CALLING_PACKAGE_1, 1);
- mInternal.onPackageBroadcast(
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
// Make sure 3, 4 and 5 still exist but disabled.
@@ -5894,7 +6011,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
R.xml.shortcut_5);
updatePackageVersion(CALLING_PACKAGE_1, 1);
- mInternal.onPackageBroadcast(
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
// Only the valid one is published.
@@ -5999,7 +6116,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
R.xml.shortcut_2);
updatePackageVersion(CALLING_PACKAGE_1, 1);
- mInternal.onPackageBroadcast(
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
@@ -6096,7 +6213,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
R.xml.shortcut_1);
updatePackageVersion(CALLING_PACKAGE_1, 1);
- mInternal.onPackageBroadcast(
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
// Only the valid one is published.
@@ -6115,7 +6232,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
R.xml.shortcut_1_disable);
updatePackageVersion(CALLING_PACKAGE_1, 1);
- mInternal.onPackageBroadcast(
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
// Because shortcut 1 wasn't pinned, it'll just go away.
@@ -6136,7 +6253,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
R.xml.shortcut_1);
updatePackageVersion(CALLING_PACKAGE_1, 1);
- mInternal.onPackageBroadcast(
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
// Only the valid one is published.
@@ -6159,7 +6276,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
R.xml.shortcut_1_disable);
updatePackageVersion(CALLING_PACKAGE_1, 1);
- mInternal.onPackageBroadcast(
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
// Because shortcut 1 was pinned, it'll still exist as pinned, but disabled.
@@ -6192,7 +6309,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
R.xml.shortcut_2_duplicate);
updatePackageVersion(CALLING_PACKAGE_1, 1);
- mInternal.onPackageBroadcast(
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
@@ -6222,7 +6339,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
new ComponentName(CALLING_PACKAGE_1, ShortcutActivity2.class.getName()),
R.xml.shortcut_5);
updatePackageVersion(CALLING_PACKAGE_1, 1);
- mInternal.onPackageBroadcast(
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
@@ -6294,7 +6411,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
R.xml.shortcut_5);
updatePackageVersion(CALLING_PACKAGE_1, 1);
- mInternal.onPackageBroadcast(
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
@@ -6344,7 +6461,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
R.xml.shortcut_2);
updatePackageVersion(CALLING_PACKAGE_1, 1);
- mInternal.onPackageBroadcast(
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
runWithCaller(LAUNCHER_1, USER_0, () -> {
@@ -6355,7 +6472,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
R.xml.shortcut_1);
updatePackageVersion(CALLING_PACKAGE_1, 1);
- mInternal.onPackageBroadcast(
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
@@ -6437,7 +6554,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
R.xml.shortcut_5);
updatePackageVersion(CALLING_PACKAGE_1, 1);
- mInternal.onPackageBroadcast(
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
@@ -6507,7 +6624,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
R.xml.shortcut_2);
updatePackageVersion(CALLING_PACKAGE_1, 1);
- mInternal.onPackageBroadcast(
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
assertEquals(2, mManager.getManifestShortcuts().size());
@@ -6633,7 +6750,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
R.xml.shortcut_2);
updatePackageVersion(CALLING_PACKAGE_1, 1);
- mInternal.onPackageBroadcast(
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
assertEquals(2, mManager.getManifestShortcuts().size());
@@ -6782,7 +6899,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
R.xml.shortcut_1);
updatePackageVersion(CALLING_PACKAGE_1, 1);
- mInternal.onPackageBroadcast(
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
assertEquals(1, mManager.getManifestShortcuts().size());
@@ -6802,7 +6919,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
new ComponentName(CALLING_PACKAGE_1, ShortcutActivity2.class.getName()),
R.xml.shortcut_1_alt);
updatePackageVersion(CALLING_PACKAGE_1, 1);
- mInternal.onPackageBroadcast(
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
assertEquals(3, mManager.getManifestShortcuts().size());
@@ -6822,7 +6939,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
new ComponentName(CALLING_PACKAGE_1, ShortcutActivity2.class.getName()),
R.xml.shortcut_5_alt); // manifest has 5, but max is 3, so a2 will have 3.
updatePackageVersion(CALLING_PACKAGE_1, 1);
- mInternal.onPackageBroadcast(
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
assertEquals(5, mManager.getManifestShortcuts().size());
@@ -6841,7 +6958,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
new ComponentName(CALLING_PACKAGE_1, ShortcutActivity2.class.getName()),
R.xml.shortcut_0);
updatePackageVersion(CALLING_PACKAGE_1, 1);
- mInternal.onPackageBroadcast(
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
assertEquals(0, mManager.getManifestShortcuts().size());
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest3.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest3.java
index fcf7ea2dcfbb..eb4db7a0f4af 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest3.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest3.java
@@ -66,7 +66,7 @@ public class ShortcutManagerTest3 extends BaseShortcutManagerTest {
private void publishManifestShortcuts(ComponentName activity, int resId) {
addManifestShortcutResource(activity, resId);
updatePackageVersion(CALLING_PACKAGE, 1);
- mInternal.onPackageBroadcast(
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageAddIntent(CALLING_PACKAGE, USER_0));
}
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutPendingTasksTest.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutPendingTasksTest.java
deleted file mode 100644
index bf1ed98983df..000000000000
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutPendingTasksTest.java
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * 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.server.pm;
-
-import android.os.Handler;
-import android.os.Looper;
-import android.test.MoreAsserts;
-import android.test.suitebuilder.annotation.LargeTest;
-
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.atomic.AtomicReference;
-
-/**
- * Run with:
- adb install \
- -r -g ${ANDROID_PRODUCT_OUT}/data/app/FrameworksServicesTests/FrameworksServicesTests.apk &&
- adb shell am instrument -e class com.android.server.pm.ShortcutPendingTasksTest \
- -w com.android.frameworks.servicestests
- */
-@LargeTest
-public class ShortcutPendingTasksTest extends BaseShortcutManagerTest {
- public void testAll() {
- final AtomicReference<Throwable> thrown = new AtomicReference<>();
-
- final AtomicBoolean threadCheckerResult = new AtomicBoolean(true);
-
- final Handler handler = new Handler(Looper.getMainLooper());
-
- final ShortcutPendingTasks tasks = new ShortcutPendingTasks(
- handler::post,
- threadCheckerResult::get,
- thrown::set);
-
- // No pending tasks, shouldn't block.
- assertTrue(tasks.waitOnAllTasks());
-
- final AtomicInteger counter = new AtomicInteger();
-
- // Run one task.
- tasks.addTask(() -> {
- try {
- Thread.sleep(1000);
- } catch (InterruptedException ignore) {
- }
- counter.incrementAndGet();
- });
-
- assertTrue(tasks.waitOnAllTasks());
- assertNull(thrown.get());
-
- assertEquals(1, counter.get());
-
- // Run 3 tasks.
-
- // We use this ID to make sure only one task can run at the same time.
- final AtomicInteger currentTaskId = new AtomicInteger();
-
- tasks.addTask(() -> {
- currentTaskId.set(1);
- try {
- Thread.sleep(500);
- } catch (InterruptedException ignore) {
- }
- counter.incrementAndGet();
- assertEquals(1, currentTaskId.get());
- });
- tasks.addTask(() -> {
- currentTaskId.set(2);
- try {
- Thread.sleep(500);
- } catch (InterruptedException ignore) {
- }
- counter.incrementAndGet();
- assertEquals(2, currentTaskId.get());
- });
- tasks.addTask(() -> {
- currentTaskId.set(3);
- try {
- Thread.sleep(500);
- } catch (InterruptedException ignore) {
- }
- counter.incrementAndGet();
- assertEquals(3, currentTaskId.get());
- });
-
- assertTrue(tasks.waitOnAllTasks());
- assertNull(thrown.get());
- assertEquals(4, counter.get());
-
- // No tasks running, shouldn't block.
- assertTrue(tasks.waitOnAllTasks());
- assertNull(thrown.get());
- assertEquals(4, counter.get());
-
- // Now the thread checker returns false, so waitOnAllTasks() returns false.
- threadCheckerResult.set(false);
- assertFalse(tasks.waitOnAllTasks());
-
- threadCheckerResult.set(true);
-
- // Make sure the exception handler is called.
- tasks.addTask(() -> {
- throw new RuntimeException("XXX");
- });
- assertTrue(tasks.waitOnAllTasks());
- assertNotNull(thrown.get());
- MoreAsserts.assertContainsRegex("XXX", thrown.get().getMessage());
- }
-}
diff --git a/tests/SoundTriggerTestApp/src/com/android/test/soundtrigger/SoundTriggerTestService.java b/tests/SoundTriggerTestApp/src/com/android/test/soundtrigger/SoundTriggerTestService.java
index 0ff95c4c49d4..a2385d695450 100644
--- a/tests/SoundTriggerTestApp/src/com/android/test/soundtrigger/SoundTriggerTestService.java
+++ b/tests/SoundTriggerTestApp/src/com/android/test/soundtrigger/SoundTriggerTestService.java
@@ -645,11 +645,11 @@ public class SoundTriggerTestService extends Service {
}
public void onAvailabilityChanged(int status) {
- postMessage(mModelInfo.name + "Availability changed to: " + status);
+ postMessage(mModelInfo.name + " availability changed to: " + status);
}
public void onDetected(SoundTriggerDetector.EventPayload event) {
- postMessage(mModelInfo.name + "onDetected(): " + eventPayloadToString(event));
+ postMessage(mModelInfo.name + " onDetected(): " + eventPayloadToString(event));
synchronized (SoundTriggerTestService.this) {
if (mUserActivity != null) {
mUserActivity.handleDetection(mModelInfo.modelUuid);
@@ -661,7 +661,7 @@ public class SoundTriggerTestService extends Service {
}
public void onError() {
- postMessage(mModelInfo.name + "onError()");
+ postMessage(mModelInfo.name + " onError()");
setModelState(mModelInfo, "Error");
}
@@ -671,7 +671,7 @@ public class SoundTriggerTestService extends Service {
}
public void onRecognitionResumed() {
- postMessage(mModelInfo.name + "onRecognitionResumed()");
+ postMessage(mModelInfo.name + " onRecognitionResumed()");
setModelState(mModelInfo, "Resumed");
}
}
diff --git a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
index 4e4da8bb3f08..49ab9f911833 100644
--- a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
+++ b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
@@ -590,4 +590,9 @@ public class IWindowManagerImpl implements IWindowManager {
@Override
public void removeWallpaperInputConsumer() throws RemoteException {}
+
+ @Override
+ public Bitmap screenshotWallpaper() throws RemoteException {
+ return null;
+ }
}