summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Android.bp1
-rw-r--r--Android.mk10
-rw-r--r--api/system-current.txt8
-rw-r--r--cmds/statsd/src/atoms.proto10
-rw-r--r--core/java/android/app/ActivityManagerInternal.java12
-rw-r--r--core/java/android/app/ActivityThread.java4
-rw-r--r--core/java/android/app/job/JobInfo.java15
-rw-r--r--core/java/android/app/usage/UsageStatsManagerInternal.java21
-rw-r--r--core/java/android/content/Context.java10
-rw-r--r--core/java/android/os/HidlSupport.java3
-rw-r--r--core/java/android/os/HwBinder.java32
-rw-r--r--core/java/android/os/IHwBinder.java14
-rw-r--r--core/java/android/os/Process.java6
-rw-r--r--core/java/android/provider/Settings.java9
-rw-r--r--core/java/android/security/keystore/RecoveryController.java2
-rw-r--r--core/java/android/security/keystore/recovery/RecoveryController.java31
-rw-r--r--core/java/android/service/notification/Condition.java18
-rw-r--r--core/java/android/service/notification/ZenModeConfig.java25
-rw-r--r--core/java/android/util/MemoryIntArray.java51
-rw-r--r--core/java/android/util/apk/ApkSignatureSchemeV3Verifier.java1
-rw-r--r--core/java/android/util/apk/ApkVerityBuilder.java20
-rw-r--r--core/java/android/view/ThreadedRenderer.java12
-rw-r--r--core/java/com/android/internal/app/EventLogTags.logtags6
-rw-r--r--core/java/com/android/internal/app/HarmfulAppWarningActivity.java59
-rw-r--r--core/java/com/android/internal/widget/ILockSettings.aidl2
-rw-r--r--core/proto/android/app/enums.proto13
-rw-r--r--core/proto/android/app/notification.proto4
-rw-r--r--core/proto/android/app/notification_channel.proto13
-rw-r--r--core/proto/android/app/notification_channel_group.proto3
-rw-r--r--core/proto/android/app/notificationmanager.proto11
-rw-r--r--core/proto/android/os/ps.proto7
-rw-r--r--core/proto/android/service/notification.proto101
-rw-r--r--core/res/AndroidManifest.xml1
-rw-r--r--core/res/res/drawable/red_shield.xml32
-rw-r--r--core/res/res/layout/harmful_app_warning_dialog.xml68
-rw-r--r--core/res/res/values/dimens.xml26
-rw-r--r--core/res/res/values/strings.xml12
-rw-r--r--core/res/res/values/symbols.xml4
-rw-r--r--core/tests/coretests/src/android/provider/SettingsBackupTest.java1
-rw-r--r--core/tests/coretests/src/com/android/internal/os/BstatsCpuTimesValidationTest.java3
-rw-r--r--packages/SettingsLib/res/values/arrays.xml12
-rw-r--r--packages/SettingsLib/res/values/strings.xml3
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionController.java174
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionControllerMixin.java140
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionLoader.java54
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/suggestions/ShadowSuggestionController.java61
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/suggestions/SuggestionControllerMixinTest.java132
-rw-r--r--packages/SystemUI/res/layout/keyguard_status_bar.xml2
-rw-r--r--packages/SystemUI/res/layout/qs_panel.xml6
-rw-r--r--packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml2
-rw-r--r--packages/SystemUI/res/layout/quick_status_bar_header_system_icons.xml2
-rw-r--r--packages/SystemUI/res/values/dimens.xml3
-rw-r--r--packages/SystemUI/res/values/strings.xml4
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java21
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarGestureHelper.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java3
-rwxr-xr-x[-rw-r--r--]packages/WAPPushManager/src/com/android/smspush/WapPushManager.java26
-rw-r--r--packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values/config.xml4
-rw-r--r--packages/overlays/DisplayCutoutEmulationTallOverlay/res/values/config.xml4
-rw-r--r--packages/overlays/DisplayCutoutEmulationWideOverlay/res/values/config.xml4
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java2
-rw-r--r--services/core/java/com/android/server/job/JobSchedulerInternal.java8
-rw-r--r--services/core/java/com/android/server/job/JobSchedulerService.java79
-rw-r--r--services/core/java/com/android/server/job/JobServiceContext.java7
-rw-r--r--services/core/java/com/android/server/locksettings/LockSettingsService.java9
-rw-r--r--services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncTask.java64
-rw-r--r--services/core/java/com/android/server/locksettings/recoverablekeystore/PlatformKeyManager.java45
-rw-r--r--services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java5
-rw-r--r--services/core/java/com/android/server/notification/NotificationManagerService.java2
-rw-r--r--services/core/java/com/android/server/notification/ZenModeHelper.java5
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java3
-rw-r--r--services/core/java/com/android/server/stats/StatsCompanionService.java6
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java6
-rw-r--r--services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java31
-rw-r--r--services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/PlatformKeyManagerTest.java68
-rw-r--r--services/tests/servicestests/src/com/android/server/net/ConnOnActivityStartTest.java3
-rw-r--r--services/usage/java/com/android/server/usage/AppIdleHistory.java41
-rw-r--r--services/usage/java/com/android/server/usage/AppStandbyController.java89
-rw-r--r--services/usage/java/com/android/server/usage/UsageStatsService.java6
-rw-r--r--telephony/java/android/telephony/data/DataService.java175
-rw-r--r--telephony/java/android/telephony/data/DataServiceCallback.java28
-rw-r--r--telephony/java/android/telephony/data/IDataService.aidl17
-rw-r--r--test-mock/Android.mk4
-rw-r--r--wifi/tests/src/android/net/wifi/ParcelUtilTest.java2
-rw-r--r--wifi/tests/src/android/net/wifi/ScanResultTest.java2
-rw-r--r--wifi/tests/src/android/net/wifi/WifiEnterpriseConfigTest.java2
-rw-r--r--wifi/tests/src/android/net/wifi/WifiManagerTest.java2
-rw-r--r--wifi/tests/src/android/net/wifi/WifiScannerTest.java2
-rw-r--r--wifi/tests/src/android/net/wifi/aware/TlvBufferUtilsTest.java2
-rw-r--r--wifi/tests/src/android/net/wifi/aware/WifiAwareAgentNetworkSpecifierTest.java2
-rw-r--r--wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java2
-rw-r--r--wifi/tests/src/android/net/wifi/hotspot2/ConfigParserTest.java2
-rw-r--r--wifi/tests/src/android/net/wifi/hotspot2/OsuProviderTest.java2
-rw-r--r--wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java2
-rw-r--r--wifi/tests/src/android/net/wifi/hotspot2/omadm/PpsMoParserTest.java2
-rw-r--r--wifi/tests/src/android/net/wifi/hotspot2/omadm/XMLParserTest.java2
-rw-r--r--wifi/tests/src/android/net/wifi/hotspot2/pps/CredentialTest.java2
-rw-r--r--wifi/tests/src/android/net/wifi/hotspot2/pps/HomeSpTest.java2
-rw-r--r--wifi/tests/src/android/net/wifi/hotspot2/pps/PolicyTest.java2
-rw-r--r--wifi/tests/src/android/net/wifi/hotspot2/pps/UpdateParameterTest.java2
102 files changed, 1698 insertions, 389 deletions
diff --git a/Android.bp b/Android.bp
index 7fac01a0f3b9..763d242a12f9 100644
--- a/Android.bp
+++ b/Android.bp
@@ -602,6 +602,7 @@ java_library {
"core/java/android/speech/tts/EventLogTags.logtags",
"core/java/android/net/EventLogTags.logtags",
"core/java/android/webkit/EventLogTags.logtags",
+ "core/java/com/android/internal/app/EventLogTags.logtags",
"core/java/com/android/internal/logging/EventLogTags.logtags",
"core/java/com/android/server/DropboxLogTags.logtags",
"core/java/org/chromium/arc/EventLogTags.logtags",
diff --git a/Android.mk b/Android.mk
index 32e4bfa57030..35b5f92be310 100644
--- a/Android.mk
+++ b/Android.mk
@@ -825,6 +825,16 @@ include $(BUILD_STATIC_JAVA_LIBRARY)
# ==== hiddenapi lists =======================================
+# Copy blacklist and dark greylist over into the build folder.
+# This is for ART buildbots which need to mock these lists and have alternative
+# rules for building them. Other rules in the build system should depend on the
+# files in the build folder.
+
+$(eval $(call copy-one-file,frameworks/base/config/hiddenapi-blacklist.txt,\
+ $(INTERNAL_PLATFORM_HIDDENAPI_BLACKLIST)))
+$(eval $(call copy-one-file,frameworks/base/config/hiddenapi-dark-greylist.txt,\
+ $(INTERNAL_PLATFORM_HIDDENAPI_DARK_GREYLIST)))
+
# Generate light greylist as private API minus (blacklist plus dark greylist).
$(INTERNAL_PLATFORM_HIDDENAPI_LIGHT_GREYLIST): PRIVATE_API := $(INTERNAL_PLATFORM_PRIVATE_DEX_API_FILE)
diff --git a/api/system-current.txt b/api/system-current.txt
index b38492092d8f..663ad112280a 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -781,6 +781,7 @@ package android.content {
field public static final java.lang.String NETWORK_SCORE_SERVICE = "network_score";
field public static final java.lang.String OEM_LOCK_SERVICE = "oem_lock";
field public static final java.lang.String PERSISTENT_DATA_BLOCK_SERVICE = "persistent_data_block";
+ field public static final java.lang.String SECURE_ELEMENT_SERVICE = "secure_element";
field public static final java.lang.String STATS_MANAGER = "stats";
field public static final java.lang.String SYSTEM_UPDATE_SERVICE = "system_update";
field public static final java.lang.String VR_SERVICE = "vrmanager";
@@ -3523,12 +3524,17 @@ package android.os {
public class HidlSupport {
method public static boolean deepEquals(java.lang.Object, java.lang.Object);
method public static int deepHashCode(java.lang.Object);
+ method public static int getPidIfSharable();
method public static boolean interfacesEqual(android.os.IHwInterface, java.lang.Object);
}
public abstract class HwBinder implements android.os.IHwBinder {
method public static final void configureRpcThreadpool(long, boolean);
+ method public static void enableInstrumentation();
+ method public static final android.os.IHwBinder getService(java.lang.String, java.lang.String) throws java.util.NoSuchElementException, android.os.RemoteException;
+ method public static final android.os.IHwBinder getService(java.lang.String, java.lang.String, boolean) throws java.util.NoSuchElementException, android.os.RemoteException;
method public static final void joinRpcThreadpool();
+ method public final void transact(int, android.os.HwParcel, android.os.HwParcel, int) throws android.os.RemoteException;
}
public class HwBlob {
@@ -3628,6 +3634,8 @@ package android.os {
public abstract interface IHwBinder {
method public abstract boolean linkToDeath(android.os.IHwBinder.DeathRecipient, long);
+ method public abstract android.os.IHwInterface queryLocalInterface(java.lang.String);
+ method public abstract void transact(int, android.os.HwParcel, android.os.HwParcel, int) throws android.os.RemoteException;
method public abstract boolean unlinkToDeath(android.os.IHwBinder.DeathRecipient);
}
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index 8f0a44a68a4b..99e871f0849f 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -837,15 +837,7 @@ message AppStartChanged {
// Device uptime when activity started.
optional int64 activity_start_msec = 7;
- // TODO: Update android/app/ActivityManagerInternal.java constants to depend on our proto enum.
- enum TransitionReason {
- APP_START_TRANSITION_REASON_UNKNOWN = 0;
- SPLASH_SCREEN = 1;
- WINDOWS_DRAWN = 2;
- TIMEOUT = 3;
- SNAPSHOT = 4;
- }
- optional TransitionReason reason = 8;
+ optional android.app.AppTransitionReasonEnum reason = 8;
optional int32 transition_delay_msec = 9;
// -1 if not set.
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index da9f72855e09..5ee7edee9db7 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -43,25 +43,29 @@ public abstract class ActivityManagerInternal {
* Type for {@link #notifyAppTransitionStarting}: The transition was started because we drew
* the splash screen.
*/
- public static final int APP_TRANSITION_SPLASH_SCREEN = 1;
+ public static final int APP_TRANSITION_SPLASH_SCREEN =
+ AppProtoEnums.APP_TRANSITION_SPLASH_SCREEN; // 1
/**
* Type for {@link #notifyAppTransitionStarting}: The transition was started because we all
* app windows were drawn
*/
- public static final int APP_TRANSITION_WINDOWS_DRAWN = 2;
+ public static final int APP_TRANSITION_WINDOWS_DRAWN =
+ AppProtoEnums.APP_TRANSITION_WINDOWS_DRAWN; // 2
/**
* Type for {@link #notifyAppTransitionStarting}: The transition was started because of a
* timeout.
*/
- public static final int APP_TRANSITION_TIMEOUT = 3;
+ public static final int APP_TRANSITION_TIMEOUT =
+ AppProtoEnums.APP_TRANSITION_TIMEOUT; // 3
/**
* Type for {@link #notifyAppTransitionStarting}: The transition was started because of a
* we drew a task snapshot.
*/
- public static final int APP_TRANSITION_SNAPSHOT = 4;
+ public static final int APP_TRANSITION_SNAPSHOT =
+ AppProtoEnums.APP_TRANSITION_SNAPSHOT; // 4
/**
* The bundle key to extract the assist data.
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 934b0f3cd4e4..3dedeea1a1b0 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -5114,6 +5114,8 @@ public final class ActivityThread extends ClientTransactionHandler {
// as that method uses the same check on the activity config override as well.
final boolean equivalent = config != null && mConfiguration != null
&& (0 == mConfiguration.diffPublicOnly(config));
+ final Theme systemTheme = getSystemContext().getTheme();
+ final Theme systemUiTheme = getSystemUiContext().getTheme();
synchronized (mResourcesManager) {
if (mPendingConfiguration != null) {
@@ -5146,12 +5148,10 @@ public final class ActivityThread extends ClientTransactionHandler {
configDiff = mConfiguration.updateFrom(config);
config = applyCompatConfiguration(mCurDefaultDisplayDpi);
- final Theme systemTheme = getSystemContext().getTheme();
if ((systemTheme.getChangingConfigurations() & configDiff) != 0) {
systemTheme.rebase();
}
- final Theme systemUiTheme = getSystemUiContext().getTheme();
if ((systemUiTheme.getChangingConfigurations() & configDiff) != 0) {
systemUiTheme.rebase();
}
diff --git a/core/java/android/app/job/JobInfo.java b/core/java/android/app/job/JobInfo.java
index cba9dcc3c4cc..a1ad825c3a29 100644
--- a/core/java/android/app/job/JobInfo.java
+++ b/core/java/android/app/job/JobInfo.java
@@ -256,6 +256,14 @@ public class JobInfo implements Parcelable {
public static final int FLAG_IS_PREFETCH = 1 << 2;
/**
+ * This job needs to be exempted from the app standby throttling. Only the system (UID 1000)
+ * can set it. Jobs with a time constrant must not have it.
+ *
+ * @hide
+ */
+ public static final int FLAG_EXEMPT_FROM_APP_STANDBY = 1 << 3;
+
+ /**
* @hide
*/
public static final int CONSTRAINT_FLAG_CHARGING = 1 << 0;
@@ -355,6 +363,13 @@ public class JobInfo implements Parcelable {
return flags;
}
+ /** @hide */
+ public boolean isExemptedFromAppStandby() {
+ return ((flags & FLAG_EXEMPT_FROM_APP_STANDBY) != 0)
+ && !hasEarlyConstraint()
+ && !hasLateConstraint();
+ }
+
/**
* Whether this job requires that the device be charging (or be a non-battery-powered
* device connected to permanent power, such as Android TV devices).
diff --git a/core/java/android/app/usage/UsageStatsManagerInternal.java b/core/java/android/app/usage/UsageStatsManagerInternal.java
index bd978e3df863..5d6a989ffef8 100644
--- a/core/java/android/app/usage/UsageStatsManagerInternal.java
+++ b/core/java/android/app/usage/UsageStatsManagerInternal.java
@@ -146,6 +146,14 @@ public abstract class UsageStatsManagerInternal {
* allowed to do work even if they're idle or in a low bucket.
*/
public abstract void onParoleStateChanged(boolean isParoleOn);
+
+ /**
+ * Optional callback to inform the listener that the app has transitioned into
+ * an active state due to user interaction.
+ */
+ public void onUserInteractionStarted(String packageName, @UserIdInt int userId) {
+ // No-op by default
+ }
}
/** Backup/Restore API */
@@ -212,4 +220,17 @@ public abstract class UsageStatsManagerInternal {
* indicated here before by a call to {@link #setLastJobRunTime(String, int, long)}.
*/
public abstract long getTimeSinceLastJobRun(String packageName, @UserIdInt int userId);
+
+ /**
+ * Report a few data points about an app's job state at the current time.
+ *
+ * @param packageName the app whose job state is being described
+ * @param userId which user the app is associated with
+ * @param numDeferredJobs the number of pending jobs that were deferred
+ * due to bucketing policy
+ * @param timeSinceLastJobRun number of milliseconds since the last time one of
+ * this app's jobs was executed
+ */
+ public abstract void reportAppJobState(String packageName, @UserIdInt int userId,
+ int numDeferredJobs, long timeSinceLastJobRun);
}
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 5177e102425a..f2eb4a0285a4 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -4170,6 +4170,16 @@ public abstract class Context {
public static final String CROSS_PROFILE_APPS_SERVICE = "crossprofileapps";
/**
+ * Use with {@link #getSystemService} to retrieve a
+ * {@link android.se.omapi.ISecureElementService}
+ * for accessing the SecureElementService.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final String SECURE_ELEMENT_SERVICE = "secure_element";
+
+ /**
* Determine whether the given permission is allowed for a particular
* process and user ID running in the system.
*
diff --git a/core/java/android/os/HidlSupport.java b/core/java/android/os/HidlSupport.java
index 335bf9d86fc7..91b796aba655 100644
--- a/core/java/android/os/HidlSupport.java
+++ b/core/java/android/os/HidlSupport.java
@@ -212,9 +212,10 @@ public class HidlSupport {
}
/**
- * Return PID of process if sharable to clients.
+ * Return PID of process only if on a non-user build. For debugging purposes.
* @hide
*/
+ @SystemApi
public static native int getPidIfSharable();
/** @hide */
diff --git a/core/java/android/os/HwBinder.java b/core/java/android/os/HwBinder.java
index ecac002940cc..2a088a659b0f 100644
--- a/core/java/android/os/HwBinder.java
+++ b/core/java/android/os/HwBinder.java
@@ -53,14 +53,30 @@ public abstract class HwBinder implements IHwBinder {
public native final void registerService(String serviceName)
throws RemoteException;
- /** @hide */
+ /**
+ * Returns the specified service from the hwservicemanager. Does not retry.
+ *
+ * @param iface fully-qualified interface name for example foo.bar@1.3::IBaz
+ * @param serviceName the instance name of the service for example default.
+ * @throws NoSuchElementException when the service is unavailable
+ * @hide
+ */
+ @SystemApi
public static final IHwBinder getService(
String iface,
String serviceName)
throws RemoteException, NoSuchElementException {
return getService(iface, serviceName, false /* retry */);
}
- /** @hide */
+ /**
+ * Returns the specified service from the hwservicemanager.
+ * @param iface fully-qualified interface name for example foo.bar@1.3::IBaz
+ * @param serviceName the instance name of the service for example default.
+ * @param retry whether to wait for the service to start if it's not already started
+ * @throws NoSuchElementException when the service is unavailable
+ * @hide
+ */
+ @SystemApi
public static native final IHwBinder getService(
String iface,
String serviceName,
@@ -108,7 +124,19 @@ public abstract class HwBinder implements IHwBinder {
private static native void native_report_sysprop_change();
/**
+ * Enable instrumentation if available.
+ * @hide
+ */
+ @SystemApi
+ public static void enableInstrumentation() {
+ native_report_sysprop_change();
+ }
+
+ /**
* Notifies listeners that a system property has changed
+ *
+ * TODO(b/72480743): remove this method
+ *
* @hide
*/
public static void reportSyspropChanged() {
diff --git a/core/java/android/os/IHwBinder.java b/core/java/android/os/IHwBinder.java
index ce9f6c1654c2..0c592e1f04b8 100644
--- a/core/java/android/os/IHwBinder.java
+++ b/core/java/android/os/IHwBinder.java
@@ -27,12 +27,22 @@ public interface IHwBinder {
/** @hide */
public static final int FLAG_ONEWAY = 1;
- /** @hide */
+ /**
+ * Process a hwbinder transaction.
+ *
+ * @hide
+ */
+ @SystemApi
public void transact(
int code, HwParcel request, HwParcel reply, int flags)
throws RemoteException;
- /** @hide */
+ /**
+ * Return as IHwInterface instance only if this implements descriptor.
+ * @param descriptor for example foo.bar@1.0::IBaz
+ * @hide
+ */
+ @SystemApi
public IHwInterface queryLocalInterface(String descriptor);
/**
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index 6833908b5c1f..96e2ae3d5ac1 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -157,6 +157,12 @@ public class Process {
*/
public static final int INCIDENTD_UID = 1067;
+ /**
+ * Defines the UID/GID for the Secure Element service process.
+ * @hide
+ */
+ public static final int SE_UID = 1068;
+
/** {@hide} */
public static final int NOBODY_UID = 9999;
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 26495cd22aff..2440b489f416 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -10503,6 +10503,15 @@ public final class Settings {
= "forced_app_standby_for_small_battery_enabled";
/**
+ * Whether or not to enable Time Only Mode for watch type devices.
+ * Type: int (0 for false, 1 for true)
+ * Default: 0
+ * @hide
+ */
+ public static final String TIME_ONLY_MODE_ENABLED
+ = "time_only_mode_enabled";
+
+ /**
* Whether or not Network Watchlist feature is enabled.
* Type: int (0 for false, 1 for true)
* Default: 0
diff --git a/core/java/android/security/keystore/RecoveryController.java b/core/java/android/security/keystore/RecoveryController.java
index 8be6d5263c53..98e6a2099012 100644
--- a/core/java/android/security/keystore/RecoveryController.java
+++ b/core/java/android/security/keystore/RecoveryController.java
@@ -167,7 +167,7 @@ public class RecoveryController {
public @NonNull KeychainSnapshot getRecoveryData(@NonNull byte[] account)
throws InternalRecoveryServiceException {
try {
- return BackwardsCompat.toLegacyKeychainSnapshot(mBinder.getRecoveryData(account));
+ return BackwardsCompat.toLegacyKeychainSnapshot(mBinder.getKeyChainSnapshot());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
} catch (ServiceSpecificException e) {
diff --git a/core/java/android/security/keystore/recovery/RecoveryController.java b/core/java/android/security/keystore/recovery/RecoveryController.java
index 71a36f19a360..4e4a0374087e 100644
--- a/core/java/android/security/keystore/recovery/RecoveryController.java
+++ b/core/java/android/security/keystore/recovery/RecoveryController.java
@@ -171,6 +171,8 @@ public class RecoveryController {
}
/**
+ * Deprecated - use getKeyChainSnapshot.
+ *
* Returns data necessary to store all recoverable keys. Key material is
* encrypted with user secret and recovery public key.
*
@@ -179,10 +181,35 @@ public class RecoveryController {
* service.
*/
@RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE)
- public @NonNull KeyChainSnapshot getRecoveryData()
+ public @Nullable KeyChainSnapshot getRecoveryData()
+ throws InternalRecoveryServiceException {
+ try {
+ return mBinder.getKeyChainSnapshot();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ } catch (ServiceSpecificException e) {
+ if (e.errorCode == ERROR_NO_SNAPSHOT_PENDING) {
+ return null;
+ }
+ throw wrapUnexpectedServiceSpecificException(e);
+ }
+ }
+
+ /**
+ * Returns data necessary to store all recoverable keys. Key material is
+ * encrypted with user secret and recovery public key.
+ *
+ * @return Data necessary to recover keystore or {@code null} if snapshot is not available.
+ * @throws InternalRecoveryServiceException if an unexpected error occurred in the recovery
+ * service.
+ *
+ * @hide
+ */
+ @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE)
+ public @Nullable KeyChainSnapshot getKeyChainSnapshot()
throws InternalRecoveryServiceException {
try {
- return mBinder.getRecoveryData(/*account=*/ new byte[]{});
+ return mBinder.getKeyChainSnapshot();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
} catch (ServiceSpecificException e) {
diff --git a/core/java/android/service/notification/Condition.java b/core/java/android/service/notification/Condition.java
index 2a352adcee18..b6c6bdc00bbe 100644
--- a/core/java/android/service/notification/Condition.java
+++ b/core/java/android/service/notification/Condition.java
@@ -18,11 +18,11 @@ package android.service.notification;
import android.annotation.IntDef;
import android.annotation.SystemApi;
-import android.app.AutomaticZenRule;
import android.content.Context;
import android.net.Uri;
import android.os.Parcel;
import android.os.Parcelable;
+import android.util.proto.ProtoOutputStream;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -161,6 +161,22 @@ public final class Condition implements Parcelable {
.append(']').toString();
}
+ /** @hide */
+ public void writeToProto(ProtoOutputStream proto, long fieldId) {
+ final long token = proto.start(fieldId);
+
+ // id is guarantreed not to be null.
+ proto.write(ConditionProto.ID, id.toString());
+ proto.write(ConditionProto.SUMMARY, summary);
+ proto.write(ConditionProto.LINE_1, line1);
+ proto.write(ConditionProto.LINE_2, line2);
+ proto.write(ConditionProto.ICON, icon);
+ proto.write(ConditionProto.STATE, state);
+ proto.write(ConditionProto.FLAGS, flags);
+
+ proto.end(token);
+ }
+
@SystemApi
public static String stateToString(int state) {
if (state == STATE_FALSE) return "STATE_FALSE";
diff --git a/core/java/android/service/notification/ZenModeConfig.java b/core/java/android/service/notification/ZenModeConfig.java
index f658ae03c927..bb88e1a20f73 100644
--- a/core/java/android/service/notification/ZenModeConfig.java
+++ b/core/java/android/service/notification/ZenModeConfig.java
@@ -33,6 +33,7 @@ import android.text.format.DateFormat;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Slog;
+import android.util.proto.ProtoOutputStream;
import com.android.internal.R;
@@ -1262,6 +1263,30 @@ public class ZenModeConfig implements Parcelable {
.append(']').toString();
}
+ /** @hide */
+ public void writeToProto(ProtoOutputStream proto, long fieldId) {
+ final long token = proto.start(fieldId);
+
+ proto.write(ZenRuleProto.ID, id);
+ proto.write(ZenRuleProto.NAME, name);
+ proto.write(ZenRuleProto.CREATION_TIME_MS, creationTime);
+ proto.write(ZenRuleProto.ENABLED, enabled);
+ proto.write(ZenRuleProto.ENABLER, enabler);
+ proto.write(ZenRuleProto.IS_SNOOZING, snoozing);
+ proto.write(ZenRuleProto.ZEN_MODE, zenMode);
+ if (conditionId != null) {
+ proto.write(ZenRuleProto.CONDITION_ID, conditionId.toString());
+ }
+ if (condition != null) {
+ condition.writeToProto(proto, ZenRuleProto.CONDITION);
+ }
+ if (component != null) {
+ component.writeToProto(proto, ZenRuleProto.COMPONENT);
+ }
+
+ proto.end(token);
+ }
+
private static void appendDiff(Diff d, String item, ZenRule from, ZenRule to) {
if (d == null) return;
if (from == null) {
diff --git a/core/java/android/util/MemoryIntArray.java b/core/java/android/util/MemoryIntArray.java
index bf335196edef..597089235e6b 100644
--- a/core/java/android/util/MemoryIntArray.java
+++ b/core/java/android/util/MemoryIntArray.java
@@ -16,13 +16,19 @@
package android.util;
+import static android.os.Process.FIRST_APPLICATION_UID;
+
import android.os.Parcel;
import android.os.ParcelFileDescriptor;
import android.os.Parcelable;
+import android.os.Process;
+
+import com.android.internal.annotations.GuardedBy;
-import libcore.io.IoUtils;
import dalvik.system.CloseGuard;
+import libcore.io.IoUtils;
+
import java.io.Closeable;
import java.io.IOException;
import java.util.UUID;
@@ -49,13 +55,18 @@ import java.util.UUID;
*/
public final class MemoryIntArray implements Parcelable, Closeable {
private static final String TAG = "MemoryIntArray";
+ private static final boolean DEBUG = Process.myUid() < FIRST_APPLICATION_UID;
private static final int MAX_SIZE = 1024;
+ private final Object mLock = new Object();
private final CloseGuard mCloseGuard = CloseGuard.get();
private final boolean mIsOwner;
private final long mMemoryAddr;
+
+ /** Fd for the shared memory object, -1 when closed */
+ @GuardedBy("mLock")
private int mFd = -1;
/**
@@ -74,6 +85,7 @@ public final class MemoryIntArray implements Parcelable, Closeable {
mFd = nativeCreate(name, size);
mMemoryAddr = nativeOpen(mFd, mIsOwner);
mCloseGuard.open("close");
+ if (DEBUG) Log.i(TAG, "created " + getString());
}
private MemoryIntArray(Parcel parcel) throws IOException {
@@ -85,6 +97,8 @@ public final class MemoryIntArray implements Parcelable, Closeable {
mFd = pfd.detachFd();
mMemoryAddr = nativeOpen(mFd, mIsOwner);
mCloseGuard.open("close");
+
+ if (DEBUG) Log.i(TAG, "created from parcel " + getString());
}
/**
@@ -141,13 +155,33 @@ public final class MemoryIntArray implements Parcelable, Closeable {
*/
@Override
public void close() throws IOException {
- if (!isClosed()) {
- nativeClose(mFd, mMemoryAddr, mIsOwner);
- mFd = -1;
- mCloseGuard.close();
+ synchronized (mLock) {
+ if (!isClosed()) {
+ if (DEBUG) {
+ try {
+ throw new Exception();
+ } catch (Exception here) {
+ Log.i(TAG, "closing " + getString(), here);
+ }
+ }
+ nativeClose(mFd, mMemoryAddr, mIsOwner);
+ mFd = -1;
+ mCloseGuard.close();
+ } else {
+ try {
+ throw new Exception();
+ } catch (Exception here) {
+ if (DEBUG) Log.i(TAG, getString() + " already closed", here);
+ }
+ }
}
}
+ private String getString() {
+ return this.getClass().getSimpleName() + "@" + System.identityHashCode(this)
+ + " mMemoryAddr=" + mMemoryAddr + " mFd=" + mFd;
+ }
+
/**
* @return Whether this array is closed and shouldn't be used.
*/
@@ -162,7 +196,9 @@ public final class MemoryIntArray implements Parcelable, Closeable {
mCloseGuard.warnIfOpen();
}
- IoUtils.closeQuietly(this);
+ if (!isClosed()) {
+ IoUtils.closeQuietly(this);
+ }
} finally {
super.finalize();
}
@@ -206,7 +242,8 @@ public final class MemoryIntArray implements Parcelable, Closeable {
private void enforceNotClosed() {
if (isClosed()) {
- throw new IllegalStateException("cannot interact with a closed instance");
+ throw new IllegalStateException("cannot interact with a closed instance "
+ + getString());
}
}
diff --git a/core/java/android/util/apk/ApkSignatureSchemeV3Verifier.java b/core/java/android/util/apk/ApkSignatureSchemeV3Verifier.java
index ee6fc072765f..a4c590f1b459 100644
--- a/core/java/android/util/apk/ApkSignatureSchemeV3Verifier.java
+++ b/core/java/android/util/apk/ApkSignatureSchemeV3Verifier.java
@@ -477,6 +477,7 @@ public class ApkSignatureSchemeV3Verifier {
}
}
+ signedData.rewind();
byte[] encodedCert = readLengthPrefixedByteArray(signedData);
int signedSigAlgorithm = signedData.getInt();
if (lastCert != null && lastSigAlgorithm != signedSigAlgorithm) {
diff --git a/core/java/android/util/apk/ApkVerityBuilder.java b/core/java/android/util/apk/ApkVerityBuilder.java
index ba21ccb808fc..4c6e511ede46 100644
--- a/core/java/android/util/apk/ApkVerityBuilder.java
+++ b/core/java/android/util/apk/ApkVerityBuilder.java
@@ -308,14 +308,6 @@ abstract class ApkVerityBuilder {
return rootHash;
}
- private static void bufferPut(ByteBuffer buffer, byte value) {
- // FIXME(b/72459251): buffer.put(value) does NOT work surprisingly. The position() after put
- // does NOT even change. This hack workaround the problem, but the root cause remains
- // unkonwn yet. This seems only happen when it goes through the apk install flow on my
- // setup.
- buffer.put(new byte[] { value });
- }
-
private static ByteBuffer generateFsverityHeader(ByteBuffer buffer, long fileSize, int depth,
byte[] salt) {
if (salt.length != 8) {
@@ -325,10 +317,10 @@ abstract class ApkVerityBuilder {
// TODO(b/30972906): update the reference when there is a better one in public.
buffer.put("TrueBrew".getBytes()); // magic
- bufferPut(buffer, (byte) 1); // major version
- bufferPut(buffer, (byte) 0); // minor version
- bufferPut(buffer, (byte) 12); // log2(block-size): log2(4096)
- bufferPut(buffer, (byte) 7); // log2(leaves-per-node): log2(4096 / 32)
+ buffer.put((byte) 1); // major version
+ buffer.put((byte) 0); // minor version
+ buffer.put((byte) 12); // log2(block-size): log2(4096)
+ buffer.put((byte) 7); // log2(leaves-per-node): log2(4096 / 32)
buffer.putShort((short) 1); // meta algorithm, SHA256_MODE == 1
buffer.putShort((short) 1); // data algorithm, SHA256_MODE == 1
@@ -338,8 +330,8 @@ abstract class ApkVerityBuilder {
buffer.putLong(fileSize); // original file size
- bufferPut(buffer, (byte) 0); // auth block offset, disabled here
- bufferPut(buffer, (byte) 2); // extension count
+ buffer.put((byte) 0); // auth block offset, disabled here
+ buffer.put((byte) 2); // extension count
buffer.put(salt); // salt (8 bytes)
// skip(buffer, 22); // reserved
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index 8b730f282b1b..370c97e37262 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -166,18 +166,6 @@ public final class ThreadedRenderer {
public static final String OVERDRAW_PROPERTY_SHOW = "show";
/**
- * Defines the rendering pipeline to be used by the ThreadedRenderer.
- *
- * Possible values:
- * "opengl", will use the existing OpenGL renderer
- * "skiagl", will use Skia's OpenGL renderer
- * "skiavk", will use Skia's Vulkan renderer
- *
- * @hide
- */
- public static final String DEBUG_RENDERER_PROPERTY = "debug.hwui.renderer";
-
- /**
* Turn on to debug non-rectangular clip operations.
*
* Possible values:
diff --git a/core/java/com/android/internal/app/EventLogTags.logtags b/core/java/com/android/internal/app/EventLogTags.logtags
new file mode 100644
index 000000000000..d681a8d26e8e
--- /dev/null
+++ b/core/java/com/android/internal/app/EventLogTags.logtags
@@ -0,0 +1,6 @@
+# See system/core/logcat/event.logtags for a description of the format of this file.
+
+option java_package com.android.internal.app;
+
+53000 harmful_app_warning_uninstall (package_name|3)
+53001 harmful_app_warning_launch_anyway (package_name|3) \ No newline at end of file
diff --git a/core/java/com/android/internal/app/HarmfulAppWarningActivity.java b/core/java/com/android/internal/app/HarmfulAppWarningActivity.java
index 042da36c98f1..99666264cb22 100644
--- a/core/java/com/android/internal/app/HarmfulAppWarningActivity.java
+++ b/core/java/com/android/internal/app/HarmfulAppWarningActivity.java
@@ -20,8 +20,12 @@ import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentSender;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
import android.os.Bundle;
import android.util.Log;
+import android.view.View;
+import android.widget.TextView;
import com.android.internal.R;
/**
@@ -31,7 +35,7 @@ import com.android.internal.R;
*/
public class HarmfulAppWarningActivity extends AlertActivity implements
DialogInterface.OnClickListener {
- private static final String TAG = "HarmfulAppWarningActivity";
+ private static final String TAG = HarmfulAppWarningActivity.class.getSimpleName();
private static final String EXTRA_HARMFUL_APP_WARNING = "harmful_app_warning";
@@ -39,13 +43,11 @@ public class HarmfulAppWarningActivity extends AlertActivity implements
private String mHarmfulAppWarning;
private IntentSender mTarget;
- // [b/63909431] STOPSHIP replace placeholder UI with final Harmful App Warning UI
-
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- Intent intent = getIntent();
+ final Intent intent = getIntent();
mPackageName = intent.getStringExtra(Intent.EXTRA_PACKAGE_NAME);
mTarget = intent.getParcelableExtra(Intent.EXTRA_INTENT);
mHarmfulAppWarning = intent.getStringExtra(EXTRA_HARMFUL_APP_WARNING);
@@ -55,33 +57,56 @@ public class HarmfulAppWarningActivity extends AlertActivity implements
finish();
}
- AlertController.AlertParams p = mAlertParams;
+ final ApplicationInfo applicationInfo;
+ try {
+ applicationInfo = getPackageManager().getApplicationInfo(mPackageName, 0 /*flags*/);
+ } catch (PackageManager.NameNotFoundException e) {
+ Log.e(TAG, "Could not show warning because package does not exist ", e);
+ finish();
+ return;
+ }
+
+ final AlertController.AlertParams p = mAlertParams;
p.mTitle = getString(R.string.harmful_app_warning_title);
- p.mMessage = mHarmfulAppWarning;
- p.mPositiveButtonText = getString(R.string.harmful_app_warning_launch_anyway);
+ p.mView = createView(applicationInfo);
+
+ p.mPositiveButtonText = getString(R.string.harmful_app_warning_uninstall);
p.mPositiveButtonListener = this;
- p.mNegativeButtonText = getString(R.string.harmful_app_warning_uninstall);
+ p.mNegativeButtonText = getString(R.string.harmful_app_warning_open_anyway);
p.mNegativeButtonListener = this;
mAlert.installContent(mAlertParams);
}
+ private View createView(ApplicationInfo applicationInfo) {
+ final View view = getLayoutInflater().inflate(R.layout.harmful_app_warning_dialog,
+ null /*root*/);
+ ((TextView) view.findViewById(R.id.app_name_text))
+ .setText(applicationInfo.loadSafeLabel(getPackageManager()));
+ ((TextView) view.findViewById(R.id.message))
+ .setText(mHarmfulAppWarning);
+ return view;
+ }
+
@Override
public void onClick(DialogInterface dialog, int which) {
switch (which) {
case DialogInterface.BUTTON_POSITIVE:
- getPackageManager().setHarmfulAppWarning(mPackageName, null);
+ getPackageManager().deletePackage(mPackageName, null /*observer*/, 0 /*flags*/);
+ EventLogTags.writeHarmfulAppWarningUninstall(mPackageName);
+ finish();
+ break;
+ case DialogInterface.BUTTON_NEGATIVE:
+ getPackageManager().setHarmfulAppWarning(mPackageName, null /*warning*/);
- IntentSender target = getIntent().getParcelableExtra(Intent.EXTRA_INTENT);
+ final IntentSender target = getIntent().getParcelableExtra(Intent.EXTRA_INTENT);
try {
- startIntentSenderForResult(target, -1, null, 0, 0, 0);
+ startIntentSenderForResult(target, -1 /*requestCode*/, null /*fillInIntent*/,
+ 0 /*flagsMask*/, 0 /*flagsValue*/, 0 /*extraFlags*/);
} catch (IntentSender.SendIntentException e) {
- // ignore..
+ Log.e(TAG, "Error while starting intent sender", e);
}
- finish();
- break;
- case DialogInterface.BUTTON_NEGATIVE:
- getPackageManager().deletePackage(mPackageName, null, 0);
+ EventLogTags.writeHarmfulAppWarningLaunchAnyway(mPackageName);
finish();
break;
}
@@ -89,7 +114,7 @@ public class HarmfulAppWarningActivity extends AlertActivity implements
public static Intent createHarmfulAppWarningIntent(Context context, String targetPackageName,
IntentSender target, CharSequence harmfulAppWarning) {
- Intent intent = new Intent();
+ final Intent intent = new Intent();
intent.setClass(context, HarmfulAppWarningActivity.class);
intent.putExtra(Intent.EXTRA_PACKAGE_NAME, targetPackageName);
intent.putExtra(Intent.EXTRA_INTENT, target);
diff --git a/core/java/com/android/internal/widget/ILockSettings.aidl b/core/java/com/android/internal/widget/ILockSettings.aidl
index 927d75753eca..5673814ca362 100644
--- a/core/java/com/android/internal/widget/ILockSettings.aidl
+++ b/core/java/com/android/internal/widget/ILockSettings.aidl
@@ -64,7 +64,7 @@ interface ILockSettings {
// {@code ServiceSpecificException} may be thrown to signal an error, which caller can
// convert to {@code RecoveryManagerException}.
void initRecoveryService(in String rootCertificateAlias, in byte[] signedPublicKeyList);
- KeyChainSnapshot getRecoveryData(in byte[] account);
+ KeyChainSnapshot getKeyChainSnapshot();
byte[] generateAndStoreKey(String alias);
void removeKey(String alias);
void setSnapshotCreatedPendingIntent(in PendingIntent intent);
diff --git a/core/proto/android/app/enums.proto b/core/proto/android/app/enums.proto
index 2de2574ad401..5eb05be1a1d1 100644
--- a/core/proto/android/app/enums.proto
+++ b/core/proto/android/app/enums.proto
@@ -21,6 +21,19 @@ package android.app;
option java_outer_classname = "AppProtoEnums";
option java_multiple_files = true;
+// ActivityManagerInternal.java's APP_TRANSITION reasons.
+enum AppTransitionReasonEnum {
+ APP_TRANSITION_REASON_UNKNOWN = 0;
+ // The transition was started because we drew the splash screen.
+ APP_TRANSITION_SPLASH_SCREEN = 1;
+ // The transition was started because we all app windows were drawn.
+ APP_TRANSITION_WINDOWS_DRAWN = 2;
+ // The transition was started because of a timeout.
+ APP_TRANSITION_TIMEOUT = 3;
+ // The transition was started because of a we drew a task snapshot.
+ APP_TRANSITION_SNAPSHOT = 4;
+}
+
// ActivityManager.java PROCESS_STATEs
enum ProcessStateEnum {
// Unlike the ActivityManager PROCESS_STATE values, the ordering and numerical values
diff --git a/core/proto/android/app/notification.proto b/core/proto/android/app/notification.proto
index 379a4ae8e2ac..c7e313aa5801 100644
--- a/core/proto/android/app/notification.proto
+++ b/core/proto/android/app/notification.proto
@@ -18,10 +18,10 @@ syntax = "proto2";
option java_package = "android.app";
option java_multiple_files = true;
-import "frameworks/base/libs/incident/proto/android/privacy.proto";
-
package android.app;
+import "frameworks/base/libs/incident/proto/android/privacy.proto";
+
/**
* An android.app.Notification object.
* Deprecated fields are not included in the proto.
diff --git a/core/proto/android/app/notification_channel.proto b/core/proto/android/app/notification_channel.proto
index 0388547e009f..337aa1c20c7a 100644
--- a/core/proto/android/app/notification_channel.proto
+++ b/core/proto/android/app/notification_channel.proto
@@ -21,19 +21,22 @@ option java_multiple_files = true;
package android.app;
import "frameworks/base/core/proto/android/media/audioattributes.proto";
+import "frameworks/base/libs/incident/proto/android/privacy.proto";
/**
* An android.app.NotificationChannel object.
*/
message NotificationChannelProto {
- optional string id = 1;
- optional string name = 2;
- optional string description = 3;
+ option (.android.msg_privacy).dest = DEST_AUTOMATIC;
+
+ optional string id = 1 [ (android.privacy).dest = DEST_EXPLICIT ];
+ optional string name = 2 [ (android.privacy).dest = DEST_EXPLICIT ];
+ optional string description = 3 [ (android.privacy).dest = DEST_EXPLICIT ];
optional int32 importance = 4;
optional bool can_bypass_dnd = 5;
// Default is VISIBILITY_NO_OVERRIDE (-1000).
optional int32 lockscreen_visibility = 6;
- optional string sound = 7;
+ optional string sound = 7 [ (android.privacy).dest = DEST_EXPLICIT ];
optional bool use_lights = 8;
// Default is 0.
optional int32 light_color = 9;
@@ -46,7 +49,7 @@ message NotificationChannelProto {
optional bool show_badge = 13;
// Default is false.
optional bool is_deleted = 14;
- optional string group = 15;
+ optional string group = 15 [ (android.privacy).dest = DEST_EXPLICIT ];
optional android.media.AudioAttributesProto audio_attributes = 16;
// If this is a blockable system notification channel.
optional bool is_blockable_system = 17;
diff --git a/core/proto/android/app/notification_channel_group.proto b/core/proto/android/app/notification_channel_group.proto
index 89a540f2012c..7b270d74f2de 100644
--- a/core/proto/android/app/notification_channel_group.proto
+++ b/core/proto/android/app/notification_channel_group.proto
@@ -21,11 +21,14 @@ option java_multiple_files = true;
package android.app;
import "frameworks/base/core/proto/android/app/notification_channel.proto";
+import "frameworks/base/libs/incident/proto/android/privacy.proto";
/**
* An android.app.NotificationChannelGroup object.
*/
message NotificationChannelGroupProto {
+ option (.android.msg_privacy).dest = DEST_EXPLICIT;
+
optional string id = 1;
optional string name = 2;
optional string description = 3;
diff --git a/core/proto/android/app/notificationmanager.proto b/core/proto/android/app/notificationmanager.proto
index 7d774aeab551..e991688c218c 100644
--- a/core/proto/android/app/notificationmanager.proto
+++ b/core/proto/android/app/notificationmanager.proto
@@ -20,10 +20,14 @@ option java_multiple_files = true;
package android.app;
+import "frameworks/base/libs/incident/proto/android/privacy.proto";
+
/**
- * An android.app.NotificationMananger.Policy object.
+ * An android.app.NotificationManager.Policy object.
*/
message PolicyProto {
+ option (.android.msg_privacy).dest = DEST_AUTOMATIC;
+
enum Category {
CATEGORY_UNKNOWN = 0;
// Reminder notifications are prioritized.
@@ -36,6 +40,11 @@ message PolicyProto {
CALLS = 4;
// Calls from repeat callers are prioritized.
REPEAT_CALLERS = 5;
+ // Alarms are prioritized.
+ ALARMS = 6;
+ // Media, system, game (catch-all for non-never suppressible sounds) are
+ // prioritized.
+ MEDIA_SYSTEM_OTHER = 7;
}
repeated Category priority_categories = 1;
diff --git a/core/proto/android/os/ps.proto b/core/proto/android/os/ps.proto
index 88c6609a92b6..9cce7274d000 100644
--- a/core/proto/android/os/ps.proto
+++ b/core/proto/android/os/ps.proto
@@ -20,10 +20,17 @@ package android.os;
option java_multiple_files = true;
+import "frameworks/base/libs/incident/proto/android/privacy.proto";
+
message PsDumpProto {
+ option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
message Process {
+ option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
// Security label, most commonly used for SELinux context data.
optional string label = 1;
+ // String representation of uid.
optional string user = 2;
// Process ID number.
optional int32 pid = 3;
diff --git a/core/proto/android/service/notification.proto b/core/proto/android/service/notification.proto
index 65df89a9a85e..9013a23664f6 100644
--- a/core/proto/android/service/notification.proto
+++ b/core/proto/android/service/notification.proto
@@ -25,8 +25,11 @@ import "frameworks/base/core/proto/android/app/notification_channel_group.proto"
import "frameworks/base/core/proto/android/app/notificationmanager.proto";
import "frameworks/base/core/proto/android/content/component_name.proto";
import "frameworks/base/core/proto/android/media/audioattributes.proto";
+import "frameworks/base/libs/incident/proto/android/privacy.proto";
message NotificationServiceDumpProto {
+ option (.android.msg_privacy).dest = DEST_AUTOMATIC;
+
repeated NotificationRecordProto records = 1;
optional ZenModeProto zen = 2;
@@ -45,7 +48,9 @@ message NotificationServiceDumpProto {
}
message NotificationRecordProto {
- optional string key = 1;
+ option (.android.msg_privacy).dest = DEST_AUTOMATIC;
+
+ optional string key = 1 [ (.android.privacy).dest = DEST_EXPLICIT ];
enum State {
ENQUEUED = 0;
@@ -54,21 +59,25 @@ message NotificationRecordProto {
}
optional State state = 2;
optional int32 flags = 3;
- optional string channelId = 4;
- optional string sound = 5;
+ optional string channelId = 4 [ (.android.privacy).dest = DEST_EXPLICIT ];
+ optional string sound = 5 [ (.android.privacy).dest = DEST_EXPLICIT ];
optional .android.media.AudioAttributesProto audio_attributes = 6;
optional bool can_vibrate = 7;
optional bool can_show_light = 8;
- optional string group_key = 9;
+ optional string group_key = 9 [ (.android.privacy).dest = DEST_EXPLICIT ];
optional int32 importance = 10;
}
message ListenersDisablingEffectsProto {
+ option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
optional int32 hint = 1;
repeated ManagedServiceInfoProto listeners = 2;
}
message ManagedServiceInfoProto {
+ option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
optional android.content.ComponentNameProto component = 1;
optional int32 user_id = 2;
optional string service = 3;
@@ -77,10 +86,14 @@ message ManagedServiceInfoProto {
}
message ManagedServicesProto {
- optional string caption = 1;
+ option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
+ optional string caption = 1 [ (.android.privacy).dest = DEST_EXPLICIT ];
message ServiceProto {
- repeated string name = 1;
+ option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
+ repeated string name = 1 [ (.android.privacy).dest = DEST_EXPLICIT ];
optional int32 user_id = 2;
optional bool is_primary = 3;
}
@@ -97,9 +110,13 @@ message ManagedServicesProto {
}
message RankingHelperProto {
+ option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
repeated string notification_signal_extractors = 1;
message RecordProto {
+ option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
optional string package = 1;
// Default value is UNKNOWN_UID = USER_NULL = -10000.
optional int32 uid = 2;
@@ -118,16 +135,72 @@ message RankingHelperProto {
repeated RecordProto records_restored_without_uid = 3;
}
-message ZenModeProto {
- enum ZenMode {
- ZEN_MODE_OFF = 0;
- ZEN_MODE_IMPORTANT_INTERRUPTIONS = 1;
- ZEN_MODE_NO_INTERRUPTIONS = 2;
- ZEN_MODE_ALARMS = 3;
+enum ZenMode {
+ ZEN_MODE_OFF = 0;
+ ZEN_MODE_IMPORTANT_INTERRUPTIONS = 1;
+ ZEN_MODE_NO_INTERRUPTIONS = 2;
+ ZEN_MODE_ALARMS = 3;
+}
+
+// An android.service.notification.Condition object.
+message ConditionProto {
+ option (android.msg_privacy).dest = DEST_EXPLICIT;
+
+ optional string id = 1;
+ optional string summary = 2;
+ optional string line_1 = 3;
+ optional string line_2 = 4;
+ optional int32 icon = 5 [ (android.privacy).dest = DEST_AUTOMATIC ];
+
+ enum State {
+ // Indicates that Do Not Disturb should be turned off.
+ STATE_FALSE = 0;
+ // Indicates that Do Not Disturb should be turned on.
+ STATE_TRUE = 1;
+ STATE_UNKNOWN = 2;
+ STATE_ERROR = 3;
}
+ optional State state = 6 [ (android.privacy).dest = DEST_AUTOMATIC ];
+
+ optional int32 flags = 7 [ (android.privacy).dest = DEST_AUTOMATIC ];
+}
+
+// An android.service.notification.ZenModeConfig.ZenRule object.
+message ZenRuleProto {
+ option (android.msg_privacy).dest = DEST_EXPLICIT;
+
+ // Required for automatic (unique).
+ optional string id = 1;
+ // Required for automatic.
+ optional string name = 2;
+ // Required for automatic.
+ optional int64 creation_time_ms = 3 [
+ (android.privacy).dest = DEST_AUTOMATIC
+ ];
+ optional bool enabled = 4 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ // Package name, only used for manual rules.
+ optional string enabler = 5 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ // User manually disabled this instance.
+ optional bool is_snoozing = 6 [
+ (android.privacy).dest = DEST_AUTOMATIC
+ ];
+ optional ZenMode zen_mode = 7 [
+ (android.privacy).dest = DEST_AUTOMATIC
+ ];
+
+ // Required for automatic.
+ optional string condition_id = 8;
+ optional ConditionProto condition = 9;
+ optional android.content.ComponentNameProto component = 10;
+}
+
+// A dump from com.android.server.notification.ZenModeHelper.
+message ZenModeProto {
+ option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
optional ZenMode zen_mode = 1;
- repeated string enabled_active_conditions = 2;
+ repeated ZenRuleProto enabled_active_conditions = 2;
optional int32 suppressed_effects = 3;
- repeated string suppressors = 4;
+ repeated android.content.ComponentNameProto suppressors = 4;
optional android.app.PolicyProto policy = 5;
}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index b23a64b9f38f..2779cd6846d4 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -3967,6 +3967,7 @@
android:theme="@style/Theme.DeviceDefault.Light.Dialog.Alert"
android:excludeFromRecents="true"
android:process=":ui"
+ android:label="@string/harmful_app_warning_title"
android:exported="false">
</activity>
diff --git a/core/res/res/drawable/red_shield.xml b/core/res/res/drawable/red_shield.xml
new file mode 100644
index 000000000000..7f425c78c708
--- /dev/null
+++ b/core/res/res/drawable/red_shield.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="34dp"
+ android:height="37dp"
+ android:viewportWidth="34"
+ android:viewportHeight="37">
+
+ <group
+ android:translateX="-3.000000"
+ android:translateY="-2.000000">
+ <path
+ android:fillType="evenOdd"
+ android:strokeWidth="1"
+ android:pathData="M 0 0 H 40 V 40 H 0 V 0 Z" />
+ <path
+ android:fillColor="#D0021B"
+ android:fillType="evenOdd"
+ android:strokeWidth="1"
+ android:pathData="M35.5858891,6.865 C27.841629,3.02166667 19.6666667,2 19.6666667,2 C19.6666667,2
+11.4917044,3.02166667 3.74744428,6.865 C3.25808614,8.915 3,11.0533333
+3,13.2533333 C3,15.515 3.27484498,17.715 3.79269315,19.8216667
+C4.89374895,24.3033333 7.09753645,28.355 10.1023965,31.6783333
+C12.7385621,34.5983333 15.9964806,36.955 19.6666667,38.5433333
+C23.3368527,36.955 26.5947712,34.5983333 29.2326127,31.6783333
+C32.2357969,28.355 34.4395844,24.3033333 35.5423161,19.8216667
+C36.0584884,17.715 36.3333333,15.515 36.3333333,13.2533333
+C36.3333333,11.0533333 36.0769231,8.915 35.5858891,6.865 M21.3333333,27.8333333
+L18,27.8333333 L18,24.5 L21.3333333,24.5 L21.3333333,27.8333333
+L21.3333333,27.8333333 Z M21.3333333,22 L18,22 L18,12 L21.3333333,12
+L21.3333333,22 L21.3333333,22 Z" />
+ </group>
+</vector> \ No newline at end of file
diff --git a/core/res/res/layout/harmful_app_warning_dialog.xml b/core/res/res/layout/harmful_app_warning_dialog.xml
new file mode 100644
index 000000000000..d41691f4bb1b
--- /dev/null
+++ b/core/res/res/layout/harmful_app_warning_dialog.xml
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2018, Google Inc.
+ *
+ * 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.
+ */
+-->
+
+<ScrollView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:fillViewport="true">
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingTop="@dimen/harmful_app_padding_top"
+ android:orientation="vertical">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingBottom="@dimen/harmful_app_name_padding_bottom"
+ android:paddingLeft="@dimen/harmful_app_name_padding_left"
+ android:paddingRight="@dimen/harmful_app_name_padding_right"
+ android:paddingTop="@dimen/harmful_app_name_padding_top"
+ android:orientation="horizontal">
+
+ <ImageView
+ android:layout_width="@dimen/harmful_app_icon_size"
+ android:layout_height="@dimen/harmful_app_icon_size"
+ android:scaleType="fitCenter"
+ android:src="@drawable/red_shield"/>
+
+ <TextView
+ android:id="@+id/app_name_text"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:gravity="center_vertical"
+ android:textColor="@color/primary_text_material_light"
+ android:textSize="@dimen/text_size_subhead_material"
+ android:paddingLeft="@dimen/harmful_app_icon_name_padding">
+ </TextView>
+ </LinearLayout>
+
+ <TextView
+ android:id="@+id/message"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:paddingLeft="@dimen/harmful_app_message_padding_left"
+ android:paddingRight="@dimen/harmful_app_message_padding_right"
+ android:paddingBottom="@dimen/harmful_app_message_padding_bottom"
+ android:lineSpacingMultiplier="@dimen/harmful_app_message_line_spacing_modifier"
+ android:textSize="@dimen/text_size_body_1_material"/>
+ </LinearLayout>
+</ScrollView> \ No newline at end of file
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index 2c824ea01be7..e57b8b242490 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -33,6 +33,10 @@
<dimen name="toast_y_offset">24dp</dimen>
<!-- Height of the status bar -->
<dimen name="status_bar_height">24dp</dimen>
+ <!-- Height of area above QQS where battery/time go -->
+ <dimen name="quick_qs_offset_height">48dp</dimen>
+ <!-- Total height of QQS (quick_qs_offset_height + 128) -->
+ <dimen name="quick_qs_total_height">176dp</dimen>
<!-- Height of the bottom navigation / system bar. -->
<dimen name="navigation_bar_height">48dp</dimen>
<!-- Height of the bottom navigation bar in portrait; often the same as @dimen/navigation_bar_height -->
@@ -635,4 +639,26 @@
<!-- Size of thumbnail used in the cross profile apps animation -->
<dimen name="cross_profile_apps_thumbnail_size">72dp</dimen>
+ <!-- Padding between the title and content in the harmful app dialog -->
+ <dimen name="harmful_app_padding_top">10dp</dimen>
+ <!-- Bottom padding for the "app name" section of the harmful app dialog -->
+ <dimen name="harmful_app_name_padding_bottom">20dp</dimen>
+ <!-- Left padding for the "app name" section of the harmful app dialog -->
+ <dimen name="harmful_app_name_padding_left">24dp</dimen>
+ <!-- Right padding for the "app name" section of the harmful app dialog -->
+ <dimen name="harmful_app_name_padding_right">24dp</dimen>
+ <!-- Top padding for the "app name" section of the harmful app dialog -->
+ <dimen name="harmful_app_name_padding_top">8dp</dimen>
+ <!-- Padding between the icon and app name in the harmful app dialog -->
+ <dimen name="harmful_app_icon_name_padding">20dp</dimen>
+ <!-- The size of the icon on the harmful app dialog -->
+ <dimen name="harmful_app_icon_size">44dp</dimen>
+ <!-- Left padding for the message section of the harmful app dialog -->
+ <dimen name="harmful_app_message_padding_left">24dp</dimen>
+ <!-- Right padding for the message section of the harmful app dialog -->
+ <dimen name="harmful_app_message_padding_right">24dp</dimen>
+ <!-- Bottom padding for the message section of the harmful app dialog -->
+ <dimen name="harmful_app_message_padding_bottom">24dp</dimen>
+ <!-- Line spacing modifier for the message field of the harmful app dialog -->
+ <item name="harmful_app_message_line_spacing_modifier" type="dimen">1.22</item>
</resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 549f9ad78423..3cde765e04cb 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -4842,12 +4842,12 @@
<!--Battery saver warning. STOPSHIP: Remove it eventually. -->
<string name="battery_saver_warning_title" translatable="false">Extreme battery saver</string>
- <!-- Label for the uninstall button on the harmful app warning dialog. -->
- <string name="harmful_app_warning_uninstall">Uninstall</string>
- <!-- Label for the launch anyway button on the harmful app warning dialog. -->
- <string name="harmful_app_warning_launch_anyway">Launch anyway</string>
- <!-- Title for the harmful app warning dialog. -->
- <string name="harmful_app_warning_title">Uninstall harmful app?</string>
+ <!-- Label for the uninstall button on the harmful app warning dialog. [CHAR LIMIT=20] -->
+ <string name="harmful_app_warning_uninstall">UNINSTALL</string>
+ <!-- Label for the open anyway button on the harmful app warning dialog. [CHAR LIMIT=20] -->
+ <string name="harmful_app_warning_open_anyway">OPEN ANYWAY</string>
+ <!-- Title for the harmful app warning dialog. [CHAR LIMIT=40] -->
+ <string name="harmful_app_warning_title">Harmful app detected</string>
<!-- Text describing a permission request for one app to show another app's
slices [CHAR LIMIT=NONE] -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 710bbfbb1b14..9442d15dfff2 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1636,6 +1636,7 @@
<java-symbol type="dimen" name="navigation_bar_height_landscape_car_mode" />
<java-symbol type="dimen" name="navigation_bar_width_car_mode" />
<java-symbol type="dimen" name="status_bar_height" />
+ <java-symbol type="dimen" name="quick_qs_total_height" />
<java-symbol type="drawable" name="ic_jog_dial_sound_off" />
<java-symbol type="drawable" name="ic_jog_dial_sound_on" />
<java-symbol type="drawable" name="ic_jog_dial_unlock" />
@@ -3228,8 +3229,9 @@
<java-symbol type="string" name="shortcut_disabled_reason_unknown" />
<java-symbol type="string" name="harmful_app_warning_uninstall" />
- <java-symbol type="string" name="harmful_app_warning_launch_anyway" />
+ <java-symbol type="string" name="harmful_app_warning_open_anyway" />
<java-symbol type="string" name="harmful_app_warning_title" />
+ <java-symbol type="layout" name="harmful_app_warning_dialog" />
<java-symbol type="string" name="config_defaultAssistantAccessPackage" />
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index 2f747ec30ef9..733f7a107fa8 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -377,6 +377,7 @@ public class SettingsBackupTest {
Settings.Global.TETHER_SUPPORTED,
Settings.Global.TEXT_CLASSIFIER_CONSTANTS,
Settings.Global.THEATER_MODE_ON,
+ Settings.Global.TIME_ONLY_MODE_ENABLED,
Settings.Global.TRANSITION_ANIMATION_SCALE,
Settings.Global.TRUSTED_SOUND,
Settings.Global.TZINFO_UPDATE_CONTENT_URL,
diff --git a/core/tests/coretests/src/com/android/internal/os/BstatsCpuTimesValidationTest.java b/core/tests/coretests/src/com/android/internal/os/BstatsCpuTimesValidationTest.java
index 4d34721b5aba..ce3ffb9e58ab 100644
--- a/core/tests/coretests/src/com/android/internal/os/BstatsCpuTimesValidationTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BstatsCpuTimesValidationTest.java
@@ -772,7 +772,8 @@ public class BstatsCpuTimesValidationTest {
latch.countDown();
}
});
- launchIntent.putExtras(extras);
+ launchIntent.putExtras(extras)
+ .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
sContext.startActivity(launchIntent);
if (latch.await(START_ACTIVITY_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
if (binders[0] == null) {
diff --git a/packages/SettingsLib/res/values/arrays.xml b/packages/SettingsLib/res/values/arrays.xml
index 77df02bc5753..c926e1ff48a7 100644
--- a/packages/SettingsLib/res/values/arrays.xml
+++ b/packages/SettingsLib/res/values/arrays.xml
@@ -468,18 +468,6 @@
<item>show_deuteranomaly</item>
</string-array>
- <!-- Titles for debug renderer preference. [CHAR LIMIT=50] -->
- <string-array name="debug_hw_renderer_entries">
- <item>OpenGL (Default)</item>
- <item>OpenGL (Skia)</item>
- </string-array>
-
- <!-- Values for debug renderer preference. -->
- <string-array name="debug_hw_renderer_values" translatable="false" >
- <item>opengl</item>
- <item>skiagl</item>
- </string-array>
-
<!-- Titles for app process limit preference. [CHAR LIMIT=35] -->
<string-array name="app_process_limit_entries">
<item>Standard limit</item>
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index 4156653c493a..486a9bbed1f2 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -679,9 +679,6 @@
<!-- UI debug setting: show the amount of overdraw in apps using the GPU [CHAR LIMIT=25] -->
<string name="debug_hw_overdraw">Debug GPU overdraw</string>
- <!-- UI debug setting: select the renderer to use by RenderThread [CHAR LIMIT=25] -->
- <string name="debug_hw_renderer">Set GPU Renderer</string>
-
<!-- UI debug setting: disable use of overlays? [CHAR LIMIT=25] -->
<string name="disable_overlays">Disable HW overlays</string>
<!-- UI debug setting: disable use of overlays summary [CHAR LIMIT=50] -->
diff --git a/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionController.java b/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionController.java
new file mode 100644
index 000000000000..f740f7c01ce1
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionController.java
@@ -0,0 +1,174 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.suggestions;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.service.settings.suggestions.ISuggestionService;
+import android.service.settings.suggestions.Suggestion;
+import android.support.annotation.Nullable;
+import android.support.annotation.WorkerThread;
+import android.util.Log;
+
+import java.util.List;
+
+/**
+ * A controller class to access suggestion data.
+ */
+public class SuggestionController {
+
+ /**
+ * Callback interface when service is connected/disconnected.
+ */
+ public interface ServiceConnectionListener {
+ /**
+ * Called when service is connected.
+ */
+ void onServiceConnected();
+
+ /**
+ * Called when service is disconnected.
+ */
+ void onServiceDisconnected();
+ }
+
+ private static final String TAG = "SuggestionController";
+ private static final boolean DEBUG = false;
+
+ private final Context mContext;
+ private final Intent mServiceIntent;
+
+ private ServiceConnection mServiceConnection;
+ private ISuggestionService mRemoteService;
+ private ServiceConnectionListener mConnectionListener;
+
+ /**
+ * Create a new controller instance.
+ *
+ * @param context caller context
+ * @param service The component name for service.
+ * @param listener listener to receive service connected/disconnected event.
+ */
+ public SuggestionController(Context context, ComponentName service,
+ ServiceConnectionListener listener) {
+ mContext = context.getApplicationContext();
+ mConnectionListener = listener;
+ mServiceIntent = new Intent().setComponent(service);
+ mServiceConnection = createServiceConnection();
+ }
+
+ /**
+ * Start the controller.
+ */
+ public void start() {
+ mContext.bindServiceAsUser(mServiceIntent, mServiceConnection, Context.BIND_AUTO_CREATE,
+ android.os.Process.myUserHandle());
+ }
+
+ /**
+ * Stop the controller.
+ */
+ public void stop() {
+ if (mRemoteService != null) {
+ mRemoteService = null;
+ mContext.unbindService(mServiceConnection);
+ }
+ }
+
+ /**
+ * Get setting suggestions.
+ */
+ @Nullable
+ @WorkerThread
+ public List<Suggestion> getSuggestions() {
+ if (!isReady()) {
+ return null;
+ }
+ try {
+ return mRemoteService.getSuggestions();
+ } catch (NullPointerException e) {
+ Log.w(TAG, "mRemote service detached before able to query", e);
+ return null;
+ } catch (RemoteException e) {
+ Log.w(TAG, "Error when calling getSuggestion()", e);
+ return null;
+ }
+ }
+
+ public void dismissSuggestions(Suggestion suggestion) {
+ if (!isReady()) {
+ Log.w(TAG, "SuggestionController not ready, cannot dismiss " + suggestion.getId());
+ return;
+ }
+ try {
+ mRemoteService.dismissSuggestion(suggestion);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Error when calling dismissSuggestion()", e);
+ }
+ }
+
+ public void launchSuggestion(Suggestion suggestion) {
+ if (!isReady()) {
+ Log.w(TAG, "SuggestionController not ready, cannot launch " + suggestion.getId());
+ return;
+ }
+
+ try {
+ mRemoteService.launchSuggestion(suggestion);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Error when calling launchSuggestion()", e);
+ }
+ }
+
+ /**
+ * Whether or not the manager is ready
+ */
+ private boolean isReady() {
+ return mRemoteService != null;
+ }
+
+ /**
+ * Create a new {@link ServiceConnection} object to handle service connect/disconnect event.
+ */
+ private ServiceConnection createServiceConnection() {
+ return new ServiceConnection() {
+
+ @Override
+ public void onServiceConnected(ComponentName name, IBinder service) {
+ if (DEBUG) {
+ Log.d(TAG, "Service is connected");
+ }
+ mRemoteService = ISuggestionService.Stub.asInterface(service);
+ if (mConnectionListener != null) {
+ mConnectionListener.onServiceConnected();
+ }
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName name) {
+ if (mConnectionListener != null) {
+ mRemoteService = null;
+ mConnectionListener.onServiceDisconnected();
+ }
+ }
+ };
+ }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionControllerMixin.java b/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionControllerMixin.java
new file mode 100644
index 000000000000..46fc32fa43cc
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionControllerMixin.java
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.suggestions;
+
+import android.app.LoaderManager;
+import android.arch.lifecycle.OnLifecycleEvent;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Loader;
+import android.os.Bundle;
+import android.service.settings.suggestions.Suggestion;
+import android.support.annotation.Nullable;
+import android.util.Log;
+
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+import java.util.List;
+
+/**
+ * Manages IPC communication to SettingsIntelligence for suggestion related services.
+ */
+public class SuggestionControllerMixin implements SuggestionController.ServiceConnectionListener,
+ android.arch.lifecycle.LifecycleObserver, LoaderManager.LoaderCallbacks<List<Suggestion>> {
+
+ public interface SuggestionControllerHost {
+ /**
+ * Called when suggestion data fetching is ready.
+ */
+ void onSuggestionReady(List<Suggestion> data);
+
+ /**
+ * Returns {@link LoaderManager} associated with the host. If host is not attached to
+ * activity then return null.
+ */
+ @Nullable
+ LoaderManager getLoaderManager();
+ }
+
+ private static final String TAG = "SuggestionCtrlMixin";
+ private static final boolean DEBUG = false;
+
+ private final Context mContext;
+ private final SuggestionController mSuggestionController;
+ private final SuggestionControllerHost mHost;
+
+ private boolean mSuggestionLoaded;
+
+ public SuggestionControllerMixin(Context context, SuggestionControllerHost host,
+ Lifecycle lifecycle, ComponentName componentName) {
+ mContext = context.getApplicationContext();
+ mHost = host;
+ mSuggestionController = new SuggestionController(mContext, componentName,
+ this /* serviceConnectionListener */);
+ if (lifecycle != null) {
+ lifecycle.addObserver(this);
+ }
+ }
+
+ @OnLifecycleEvent(Lifecycle.Event.ON_START)
+ public void onStart() {
+ if (DEBUG) {
+ Log.d(TAG, "SuggestionController started");
+ }
+ mSuggestionController.start();
+ }
+
+ @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
+ public void onStop() {
+ if (DEBUG) {
+ Log.d(TAG, "SuggestionController stopped.");
+ }
+ mSuggestionController.stop();
+ }
+
+ @Override
+ public void onServiceConnected() {
+ final LoaderManager loaderManager = mHost.getLoaderManager();
+ if (loaderManager != null) {
+ loaderManager.restartLoader(SuggestionLoader.LOADER_ID_SUGGESTIONS,
+ null /* args */, this /* callback */);
+ }
+ }
+
+ @Override
+ public void onServiceDisconnected() {
+ if (DEBUG) {
+ Log.d(TAG, "SuggestionService disconnected");
+ }
+ final LoaderManager loaderManager = mHost.getLoaderManager();
+ if (loaderManager != null) {
+ loaderManager.destroyLoader(SuggestionLoader.LOADER_ID_SUGGESTIONS);
+ }
+ }
+
+ @Override
+ public Loader<List<Suggestion>> onCreateLoader(int id, Bundle args) {
+ if (id == SuggestionLoader.LOADER_ID_SUGGESTIONS) {
+ mSuggestionLoaded = false;
+ return new SuggestionLoader(mContext, mSuggestionController);
+ }
+ throw new IllegalArgumentException("This loader id is not supported " + id);
+ }
+
+ @Override
+ public void onLoadFinished(Loader<List<Suggestion>> loader, List<Suggestion> data) {
+ mSuggestionLoaded = true;
+ mHost.onSuggestionReady(data);
+ }
+
+ @Override
+ public void onLoaderReset(Loader<List<Suggestion>> loader) {
+ mSuggestionLoaded = false;
+ }
+
+ public boolean isSuggestionLoaded() {
+ return mSuggestionLoaded;
+ }
+
+ public void dismissSuggestion(Suggestion suggestion) {
+ mSuggestionController.dismissSuggestions(suggestion);
+ }
+
+ public void launchSuggestion(Suggestion suggestion) {
+ mSuggestionController.launchSuggestion(suggestion);
+ }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionLoader.java b/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionLoader.java
new file mode 100644
index 000000000000..9c1af1edc778
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionLoader.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.suggestions;
+
+import android.content.Context;
+import android.service.settings.suggestions.Suggestion;
+import android.util.Log;
+
+import com.android.settingslib.utils.AsyncLoader;
+
+import java.util.List;
+
+public class SuggestionLoader extends AsyncLoader<List<Suggestion>> {
+
+ public static final int LOADER_ID_SUGGESTIONS = 42;
+ private static final String TAG = "SuggestionLoader";
+
+ private final SuggestionController mSuggestionController;
+
+ public SuggestionLoader(Context context, SuggestionController controller) {
+ super(context);
+ mSuggestionController = controller;
+ }
+
+ @Override
+ protected void onDiscardResult(List<Suggestion> result) {
+
+ }
+
+ @Override
+ public List<Suggestion> loadInBackground() {
+ final List<Suggestion> data = mSuggestionController.getSuggestions();
+ if (data == null) {
+ Log.d(TAG, "data is null");
+ } else {
+ Log.d(TAG, "data size " + data.size());
+ }
+ return data;
+ }
+} \ No newline at end of file
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/suggestions/ShadowSuggestionController.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/suggestions/ShadowSuggestionController.java
new file mode 100644
index 000000000000..61bc83b8f72e
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/suggestions/ShadowSuggestionController.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.suggestions;
+
+import android.service.settings.suggestions.Suggestion;
+
+import org.robolectric.annotation.Implementation;
+import org.robolectric.annotation.Implements;
+
+import java.util.List;
+
+@Implements(SuggestionController.class)
+public class ShadowSuggestionController {
+
+ public static boolean sStartCalled;
+ public static boolean sStopCalled;
+ public static boolean sGetSuggestionCalled;
+
+ public static List<Suggestion> sSuggestions;
+
+ public static void reset() {
+ sStartCalled = false;
+ sStopCalled = false;
+ sGetSuggestionCalled = false;
+ sSuggestions = null;
+ }
+
+ @Implementation
+ public void start() {
+ sStartCalled = true;
+ }
+
+ @Implementation
+ public void stop() {
+ sStopCalled = true;
+ }
+
+ public static void setSuggestion(List<Suggestion> suggestions) {
+ sSuggestions = suggestions;
+ }
+
+ @Implementation
+ public List<Suggestion> getSuggestions() {
+ sGetSuggestionCalled = true;
+ return sSuggestions;
+ }
+}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/suggestions/SuggestionControllerMixinTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/suggestions/SuggestionControllerMixinTest.java
new file mode 100644
index 000000000000..ed1c405f8a81
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/suggestions/SuggestionControllerMixinTest.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.suggestions;
+
+import static android.arch.lifecycle.Lifecycle.Event.ON_START;
+import static android.arch.lifecycle.Lifecycle.Event.ON_STOP;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.LoaderManager;
+import android.arch.lifecycle.LifecycleOwner;
+import android.content.ComponentName;
+import android.content.Context;
+
+import com.android.settingslib.TestConfig;
+import com.android.settingslib.SettingsLibRobolectricTestRunner;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+@RunWith(SettingsLibRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION,
+ shadows = {
+ ShadowSuggestionController.class
+ })
+public class SuggestionControllerMixinTest {
+
+ @Mock
+ private SuggestionControllerMixin.SuggestionControllerHost mHost;
+
+ private Context mContext;
+ private LifecycleOwner mLifecycleOwner;
+ private Lifecycle mLifecycle;
+ private SuggestionControllerMixin mMixin;
+ private ComponentName mComponentName;
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mContext = RuntimeEnvironment.application;
+ mLifecycleOwner = () -> mLifecycle;
+ mLifecycle = new Lifecycle(mLifecycleOwner);
+ mComponentName = new ComponentName(
+ "com.android.settings.intelligence",
+ "com.android.settings.intelligence.suggestions.SuggestionService");
+ }
+
+ @After
+ public void tearDown() {
+ ShadowSuggestionController.reset();
+ }
+
+ @Test
+ public void goThroughLifecycle_onStartStop_shouldStartStopController() {
+ mMixin = new SuggestionControllerMixin(mContext, mHost, mLifecycle, mComponentName);
+
+ mLifecycle.handleLifecycleEvent(ON_START);
+ assertThat(ShadowSuggestionController.sStartCalled).isTrue();
+
+ mLifecycle.handleLifecycleEvent(ON_STOP);
+ assertThat(ShadowSuggestionController.sStopCalled).isTrue();
+ }
+
+ @Test
+ public void onServiceConnected_shouldGetSuggestion() {
+ final LoaderManager loaderManager = mock(LoaderManager.class);
+ when(mHost.getLoaderManager()).thenReturn(loaderManager);
+
+ mMixin = new SuggestionControllerMixin(mContext, mHost, mLifecycle, mComponentName);
+ mMixin.onServiceConnected();
+
+ verify(loaderManager).restartLoader(SuggestionLoader.LOADER_ID_SUGGESTIONS,
+ null /* args */, mMixin /* callback */);
+ }
+
+ @Test
+ public void onServiceConnected_hostNotAttached_shouldDoNothing() {
+ when(mHost.getLoaderManager()).thenReturn(null);
+
+ mMixin = new SuggestionControllerMixin(mContext, mHost, mLifecycle, mComponentName);
+ mMixin.onServiceConnected();
+
+ verify(mHost).getLoaderManager();
+ }
+
+ @Test
+ public void onServiceDisconnected_hostNotAttached_shouldDoNothing() {
+ when(mHost.getLoaderManager()).thenReturn(null);
+
+ mMixin = new SuggestionControllerMixin(mContext, mHost, mLifecycle, mComponentName);
+ mMixin.onServiceDisconnected();
+
+ verify(mHost).getLoaderManager();
+ }
+
+ @Test
+ public void doneLoadingg_shouldSetSuggestionLoaded() {
+ mMixin = new SuggestionControllerMixin(mContext, mHost, mLifecycle, mComponentName);
+
+ mMixin.onLoadFinished(mock(SuggestionLoader.class), null);
+
+ assertThat(mMixin.isSuggestionLoaded()).isTrue();
+
+ mMixin.onLoaderReset(mock(SuggestionLoader.class));
+
+ assertThat(mMixin.isSuggestionLoaded()).isFalse();
+ }
+}
diff --git a/packages/SystemUI/res/layout/keyguard_status_bar.xml b/packages/SystemUI/res/layout/keyguard_status_bar.xml
index 7b30d6ae8717..cd1be152b8d2 100644
--- a/packages/SystemUI/res/layout/keyguard_status_bar.xml
+++ b/packages/SystemUI/res/layout/keyguard_status_bar.xml
@@ -40,7 +40,7 @@
<LinearLayout android:id="@+id/system_icons_super_container"
android:layout_width="wrap_content"
- android:layout_height="@dimen/status_bar_header_height"
+ android:layout_height="@*android:dimen/quick_qs_total_height"
android:layout_toStartOf="@id/multi_user_switch"
android:layout_alignWithParentIfMissing="true"
android:layout_marginStart="@dimen/system_icons_super_container_margin_start"
diff --git a/packages/SystemUI/res/layout/qs_panel.xml b/packages/SystemUI/res/layout/qs_panel.xml
index 5bcb7fd2685e..1dab76183864 100644
--- a/packages/SystemUI/res/layout/qs_panel.xml
+++ b/packages/SystemUI/res/layout/qs_panel.xml
@@ -33,7 +33,7 @@
<View
android:id="@+id/quick_settings_status_bar_background"
android:layout_width="match_parent"
- android:layout_height="@dimen/qs_header_system_icons_area_height"
+ android:layout_height="@*android:dimen/quick_qs_offset_height"
android:clipToPadding="false"
android:clipChildren="false"
android:background="#ff000000" />
@@ -43,7 +43,7 @@
android:id="@+id/quick_settings_gradient_view"
android:layout_width="match_parent"
android:layout_height="126dp"
- android:layout_marginTop="@dimen/qs_header_system_icons_area_height"
+ android:layout_marginTop="@*android:dimen/quick_qs_offset_height"
android:clipToPadding="false"
android:clipChildren="false"
android:background="@drawable/qs_bg_gradient" />
@@ -51,7 +51,7 @@
<com.android.systemui.qs.QSPanel
android:id="@+id/quick_settings_panel"
- android:layout_marginTop="@dimen/qs_header_system_icons_area_height"
+ android:layout_marginTop="@*android:dimen/quick_qs_offset_height"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="48dp"
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 dacc3f96220b..cc79d0d9b7dd 100644
--- a/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
+++ b/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
@@ -20,7 +20,7 @@
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/header"
android:layout_width="match_parent"
- android:layout_height="@dimen/status_bar_header_height"
+ android:layout_height="@*android:dimen/quick_qs_total_height"
android:layout_gravity="@integer/notification_panel_layout_gravity"
android:baselineAligned="false"
android:clickable="false"
diff --git a/packages/SystemUI/res/layout/quick_status_bar_header_system_icons.xml b/packages/SystemUI/res/layout/quick_status_bar_header_system_icons.xml
index 2c69501106a6..f38129f0dffa 100644
--- a/packages/SystemUI/res/layout/quick_status_bar_header_system_icons.xml
+++ b/packages/SystemUI/res/layout/quick_status_bar_header_system_icons.xml
@@ -19,7 +19,7 @@
xmlns:systemui="http://schemas.android.com/apk/res-auto"
android:id="@+id/quick_status_bar_system_icons"
android:layout_width="match_parent"
- android:layout_height="@dimen/qs_header_system_icons_area_height"
+ android:layout_height="@*android:dimen/quick_qs_offset_height"
android:layout_alignParentEnd="true"
android:clipChildren="false"
android:clipToPadding="false"
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index d58c725c6462..3db79d7556d5 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -214,9 +214,6 @@
<!-- Amount of close_handle that will NOT overlap the notification list -->
<dimen name="close_handle_underlap">32dp</dimen>
- <!-- Height of the status bar header bar -->
- <dimen name="status_bar_header_height">178dp</dimen>
-
<!-- Height of the status bar header bar in the car setting. -->
<dimen name="car_status_bar_header_height">128dp</dimen>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 6d61a0c198f9..9b6af43a1920 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -771,8 +771,10 @@
<string name="quick_settings_tethering_label">Tethering</string>
<!-- QuickSettings: Hotspot. [CHAR LIMIT=NONE] -->
<string name="quick_settings_hotspot_label">Hotspot</string>
+ <!-- QuickSettings: Hotspot. Secondary label shown when the hotspot is being enabled [CHAR LIMIT=NONE] -->
+ <string name="quick_settings_hotspot_secondary_label_transient">Turning on...</string>
<!-- QuickSettings: Hotspot: Secondary label for how many devices are connected to the hotspot [CHAR LIMIT=NONE] -->
- <plurals name="quick_settings_hotspot_num_devices">
+ <plurals name="quick_settings_hotspot_secondary_label_num_devices">
<item quantity="one">%d device</item>
<item quantity="other">%d devices</item>
</plurals>
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
index 17ede6586402..77768b1a4bd1 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
@@ -166,7 +166,8 @@ public class QuickStatusBarHeader extends RelativeLayout
if (disabled == mQsDisabled) return;
mQsDisabled = disabled;
mHeaderQsPanel.setDisabledByPolicy(disabled);
- final int rawHeight = (int) getResources().getDimension(R.dimen.status_bar_header_height);
+ final int rawHeight = (int) getResources().getDimension(
+ com.android.internal.R.dimen.quick_qs_total_height);
getLayoutParams().height = disabled ? (rawHeight - mHeaderQsPanel.getHeight()) : rawHeight;
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
index e1b58fe4c2d6..080e320802e6 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
@@ -113,11 +113,11 @@ public class HotspotTile extends QSTileImpl<AirplaneBooleanState> {
if (state.slash == null) {
state.slash = new SlashState();
}
- state.label = mContext.getString(R.string.quick_settings_hotspot_label);
-
- checkIfRestrictionEnforcedByAdminOnly(state, UserManager.DISALLOW_CONFIG_TETHERING);
final int numConnectedDevices;
+ final boolean isTransient = mController.isHotspotTransient();
+
+ checkIfRestrictionEnforcedByAdminOnly(state, UserManager.DISALLOW_CONFIG_TETHERING);
if (arg instanceof CallbackInfo) {
CallbackInfo info = (CallbackInfo) arg;
state.value = info.enabled;
@@ -127,11 +127,11 @@ public class HotspotTile extends QSTileImpl<AirplaneBooleanState> {
numConnectedDevices = mController.getNumConnectedDevices();
}
- state.secondaryLabel = getSecondaryLabel(state.value, numConnectedDevices);
-
state.icon = mEnabledStatic;
+ state.label = mContext.getString(R.string.quick_settings_hotspot_label);
+ state.secondaryLabel = getSecondaryLabel(state.value, isTransient, numConnectedDevices);
state.isAirplaneMode = mAirplaneMode.getValue() != 0;
- state.isTransient = mController.isHotspotTransient();
+ state.isTransient = isTransient;
state.slash.isSlashed = !state.value && !state.isTransient;
if (state.isTransient) {
state.icon = ResourceIcon.get(R.drawable.ic_hotspot_transient_animation);
@@ -143,10 +143,13 @@ public class HotspotTile extends QSTileImpl<AirplaneBooleanState> {
}
@Nullable
- private String getSecondaryLabel(boolean enabled, int numConnectedDevices) {
- if (numConnectedDevices > 0 && enabled) {
+ private String getSecondaryLabel(
+ boolean enabled, boolean isTransient, int numConnectedDevices) {
+ if (isTransient) {
+ return mContext.getString(R.string.quick_settings_hotspot_secondary_label_transient);
+ } else if (numConnectedDevices > 0 && enabled) {
return mContext.getResources().getQuantityString(
- R.plurals.quick_settings_hotspot_num_devices,
+ R.plurals.quick_settings_hotspot_secondary_label_num_devices,
numConnectedDevices,
numConnectedDevices);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
index da809c12d16c..09acf3e4b53b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
@@ -115,7 +115,7 @@ public class KeyguardStatusBarView extends RelativeLayout
lp = (MarginLayoutParams) mSystemIconsSuperContainer.getLayoutParams();
lp.height = getResources().getDimensionPixelSize(
- R.dimen.status_bar_header_height);
+ com.android.internal.R.dimen.quick_qs_total_height);
lp.setMarginStart(getResources().getDimensionPixelSize(
R.dimen.system_icons_super_container_margin_start));
mSystemIconsSuperContainer.setLayoutParams(lp);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarGestureHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarGestureHelper.java
index 0954fd054e2d..0d36efda9ece 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarGestureHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarGestureHelper.java
@@ -308,8 +308,13 @@ public class NavigationBarGestureHelper implements TunerService.Tunable, Gesture
}
public boolean onTouchEvent(MotionEvent event) {
+ // The same down event was just sent on intercept and therefore can be ignored here
+ boolean ignoreProxyDownEvent = event.getAction() == MotionEvent.ACTION_DOWN
+ && mOverviewEventSender.getProxy() != null;
boolean result = mStatusBar.isPresenterFullyCollapsed()
- && (mQuickScrubController.onTouchEvent(event) || proxyMotionEvents(event));
+ && (mQuickScrubController.onTouchEvent(event)
+ || ignoreProxyDownEvent
+ || proxyMotionEvents(event));
if (mDockWindowEnabled) {
result |= handleDockWindowEvent(event);
}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
index 56b7201ea274..3e13ddb1028a 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
@@ -341,7 +341,8 @@ public class VolumeDialogImpl implements VolumeDialog {
row.connectedDevice = row.view.findViewById(R.id.volume_row_connected_device);
// forward events above the slider into the slider
- row.view.setOnTouchListener(new OnTouchListener() {
+ row.view.findViewById(R.id.volume_row_slider_frame)
+ .setOnTouchListener(new OnTouchListener() {
private final Rect mSliderHitRect = new Rect();
private boolean mDragging;
diff --git a/packages/WAPPushManager/src/com/android/smspush/WapPushManager.java b/packages/WAPPushManager/src/com/android/smspush/WapPushManager.java
index e9703670008d..dc2707b6ff8b 100644..100755
--- a/packages/WAPPushManager/src/com/android/smspush/WapPushManager.java
+++ b/packages/WAPPushManager/src/com/android/smspush/WapPushManager.java
@@ -22,11 +22,15 @@ import android.content.ComponentName;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
import android.database.Cursor;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteDatabase;
+import android.os.Build;
import android.os.IBinder;
+import android.os.PowerManager;
import android.os.RemoteException;
import android.util.Log;
@@ -216,7 +220,27 @@ public class WapPushManager extends Service {
intent.setClassName(mContext, lastapp.className);
intent.setComponent(new ComponentName(lastapp.packageName,
lastapp.className));
- if (mContext.startService(intent) == null) {
+ PackageManager pm = mContext.getPackageManager();
+ PowerManager powerManager =
+ (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
+ try {
+ ApplicationInfo appInfo = pm.getApplicationInfo(lastapp.packageName, 0);
+ if (appInfo.targetSdkVersion < Build.VERSION_CODES.O ||
+ powerManager.isIgnoringBatteryOptimizations(lastapp.packageName)) {
+ if (mContext.startService(intent) == null) {
+ Log.w(LOG_TAG, "invalid name " +
+ lastapp.packageName + "/" + lastapp.className);
+ return WapPushManagerParams.INVALID_RECEIVER_NAME;
+ }
+ } else {
+ if (mContext.startForegroundService(intent) == null) {
+ Log.w(LOG_TAG, "invalid name " +
+ lastapp.packageName + "/" + lastapp.className);
+ return WapPushManagerParams.INVALID_RECEIVER_NAME;
+ }
+ }
+
+ } catch (NameNotFoundException e) {
Log.w(LOG_TAG, "invalid name " +
lastapp.packageName + "/" + lastapp.className);
return WapPushManagerParams.INVALID_RECEIVER_NAME;
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values/config.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values/config.xml
index 43bde88dabdd..a584a7f3fb90 100644
--- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values/config.xml
+++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values/config.xml
@@ -47,6 +47,10 @@
<!-- Height of the status bar -->
<dimen name="status_bar_height">48dp</dimen>
+ <!-- Height of area above QQS where battery/time go (equal to status bar height if > 48dp) -->
+ <dimen name="quick_qs_offset_height">48dp</dimen>
+ <!-- Total height of QQS (quick_qs_offset_height + 128) -->
+ <dimen name="quick_qs_total_height">176dp</dimen>
</resources>
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values/config.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values/config.xml
index 9cf48d9e15a8..915e16412155 100644
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values/config.xml
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values/config.xml
@@ -47,6 +47,10 @@
<!-- Height of the status bar -->
<dimen name="status_bar_height">48dp</dimen>
+ <!-- Height of area above QQS where battery/time go (equal to status bar height if > 48dp) -->
+ <dimen name="quick_qs_offset_height">48dp</dimen>
+ <!-- Total height of QQS (quick_qs_offset_height + 128) -->
+ <dimen name="quick_qs_total_height">176dp</dimen>
</resources>
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values/config.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values/config.xml
index 1ce41f07691d..b8e29da8c8e7 100644
--- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values/config.xml
+++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values/config.xml
@@ -47,6 +47,10 @@
<!-- Height of the status bar -->
<dimen name="status_bar_height">48dp</dimen>
+ <!-- Height of area above QQS where battery/time go (equal to status bar height if > 48dp) -->
+ <dimen name="quick_qs_offset_height">48dp</dimen>
+ <!-- Total height of QQS (quick_qs_offset_height + 128) -->
+ <dimen name="quick_qs_total_height">176dp</dimen>
</resources>
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index f658b276d3ab..520fdceead7c 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -87,6 +87,7 @@ import static android.os.Process.ROOT_UID;
import static android.os.Process.SCHED_FIFO;
import static android.os.Process.SCHED_OTHER;
import static android.os.Process.SCHED_RESET_ON_FORK;
+import static android.os.Process.SE_UID;
import static android.os.Process.SHELL_UID;
import static android.os.Process.SIGNAL_QUIT;
import static android.os.Process.SIGNAL_USR1;
@@ -20725,6 +20726,7 @@ public class ActivityManagerService extends IActivityManager.Stub
case PHONE_UID:
case BLUETOOTH_UID:
case NFC_UID:
+ case SE_UID:
isCallerSystem = true;
break;
default:
diff --git a/services/core/java/com/android/server/job/JobSchedulerInternal.java b/services/core/java/com/android/server/job/JobSchedulerInternal.java
index 569e9ec995d7..08607bc8ef2c 100644
--- a/services/core/java/com/android/server/job/JobSchedulerInternal.java
+++ b/services/core/java/com/android/server/job/JobSchedulerInternal.java
@@ -64,6 +64,14 @@ public interface JobSchedulerInternal {
void removeBackingUpUid(int uid);
void clearAllBackingUpUids();
+ /**
+ * The user has started interacting with the app. Take any appropriate action.
+ */
+ void reportAppUsage(String packageName, int userId);
+
+ /**
+ * Report a snapshot of sync-related jobs back to the sync manager
+ */
JobStorePersistStats getPersistStats();
/**
diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java
index 2066f2af46dd..8fa331880abc 100644
--- a/services/core/java/com/android/server/job/JobSchedulerService.java
+++ b/services/core/java/com/android/server/job/JobSchedulerService.java
@@ -1071,6 +1071,11 @@ public final class JobSchedulerService extends com.android.server.SystemService
}
}
+ void reportAppUsage(String packageName, int userId) {
+ // This app just transitioned into interactive use or near equivalent, so we should
+ // take a look at its job state for feedback purposes.
+ }
+
/**
* Initializes the system service.
* <p>
@@ -1809,7 +1814,9 @@ public final class JobSchedulerService extends com.android.server.SystemService
// If the app is in a non-active standby bucket, make sure we've waited
// an appropriate amount of time since the last invocation. During device-
// wide parole, standby bucketing is ignored.
- if (!mInParole) {
+ //
+ // But if a job has FLAG_EXEMPT_FROM_APP_STANDBY, don't check it.
+ if (!mInParole && !job.getJob().isExemptedFromAppStandby()) {
final int bucket = job.getStandbyBucket();
if (mHeartbeat < mNextBucketHeartbeat[bucket]) {
// Only skip this job if it's still waiting for the end of its (initial) nominal
@@ -2151,6 +2158,11 @@ public final class JobSchedulerService extends com.android.server.SystemService
}
@Override
+ public void reportAppUsage(String packageName, int userId) {
+ JobSchedulerService.this.reportAppUsage(packageName, userId);
+ }
+
+ @Override
public JobStorePersistStats getPersistStats() {
synchronized (mLock) {
return new JobStorePersistStats(mJobs.getPersistStats());
@@ -2212,6 +2224,40 @@ public final class JobSchedulerService extends com.android.server.SystemService
}
mInParole = isParoleOn;
}
+
+ @Override
+ public void onUserInteractionStarted(String packageName, int userId) {
+ final int uid = mLocalPM.getPackageUid(packageName,
+ PackageManager.MATCH_UNINSTALLED_PACKAGES, userId);
+ if (uid < 0) {
+ // Quietly ignore; the case is already logged elsewhere
+ return;
+ }
+
+ final long sinceLast = sElapsedRealtimeClock.millis() -
+ mUsageStats.getTimeSinceLastJobRun(packageName, userId);
+ final DeferredJobCounter counter = new DeferredJobCounter();
+ synchronized (mLock) {
+ mJobs.forEachJobForSourceUid(uid, counter);
+ }
+
+ mUsageStats.reportAppJobState(packageName, userId, counter.numDeferred(), sinceLast);
+ }
+ }
+
+ static class DeferredJobCounter implements JobStatusFunctor {
+ private int mDeferred = 0;
+
+ public int numDeferred() {
+ return mDeferred;
+ }
+
+ @Override
+ public void process(JobStatus job) {
+ if (job.getWhenStandbyDeferred() > 0) {
+ mDeferred++;
+ }
+ }
}
public static int standbyBucketToBucketIndex(int bucket) {
@@ -2295,6 +2341,22 @@ public final class JobSchedulerService extends com.android.server.SystemService
return canPersist;
}
+ private void validateJobFlags(JobInfo job, int callingUid) {
+ if ((job.getFlags() & JobInfo.FLAG_WILL_BE_FOREGROUND) != 0) {
+ getContext().enforceCallingOrSelfPermission(
+ android.Manifest.permission.CONNECTIVITY_INTERNAL, TAG);
+ }
+ if ((job.getFlags() & JobInfo.FLAG_EXEMPT_FROM_APP_STANDBY) != 0) {
+ if (callingUid != Process.SYSTEM_UID) {
+ throw new SecurityException("Job has invalid flags");
+ }
+ if (job.hasLateConstraint() || job.hasEarlyConstraint()) {
+ Slog.wtf(TAG, "Jobs with time-constraints mustn't have"
+ +" FLAG_EXEMPT_FROM_APP_STANDBY. Job=" + job);
+ }
+ }
+ }
+
// IJobScheduler implementation
@Override
public int schedule(JobInfo job) throws RemoteException {
@@ -2313,10 +2375,7 @@ public final class JobSchedulerService extends com.android.server.SystemService
}
}
- if ((job.getFlags() & JobInfo.FLAG_WILL_BE_FOREGROUND) != 0) {
- getContext().enforceCallingOrSelfPermission(
- android.Manifest.permission.CONNECTIVITY_INTERNAL, TAG);
- }
+ validateJobFlags(job, uid);
long ident = Binder.clearCallingIdentity();
try {
@@ -2344,10 +2403,7 @@ public final class JobSchedulerService extends com.android.server.SystemService
throw new NullPointerException("work is null");
}
- if ((job.getFlags() & JobInfo.FLAG_WILL_BE_FOREGROUND) != 0) {
- getContext().enforceCallingOrSelfPermission(
- android.Manifest.permission.CONNECTIVITY_INTERNAL, TAG);
- }
+ validateJobFlags(job, uid);
long ident = Binder.clearCallingIdentity();
try {
@@ -2378,10 +2434,7 @@ public final class JobSchedulerService extends com.android.server.SystemService
+ " not permitted to schedule jobs for other apps");
}
- if ((job.getFlags() & JobInfo.FLAG_WILL_BE_FOREGROUND) != 0) {
- getContext().enforceCallingOrSelfPermission(
- android.Manifest.permission.CONNECTIVITY_INTERNAL, TAG);
- }
+ validateJobFlags(job, callerUid);
long ident = Binder.clearCallingIdentity();
try {
diff --git a/services/core/java/com/android/server/job/JobServiceContext.java b/services/core/java/com/android/server/job/JobServiceContext.java
index f23147b445c2..37b39907e976 100644
--- a/services/core/java/com/android/server/job/JobServiceContext.java
+++ b/services/core/java/com/android/server/job/JobServiceContext.java
@@ -24,6 +24,7 @@ import android.app.job.IJobService;
import android.app.job.JobInfo;
import android.app.job.JobParameters;
import android.app.job.JobWorkItem;
+import android.app.usage.UsageStatsManagerInternal;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -46,6 +47,7 @@ import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.IBatteryStats;
import com.android.server.EventLogTags;
+import com.android.server.LocalServices;
import com.android.server.job.controllers.JobStatus;
/**
@@ -238,6 +240,11 @@ public final class JobServiceContext implements ServiceConnection {
}
}
+ UsageStatsManagerInternal usageStats =
+ LocalServices.getService(UsageStatsManagerInternal.class);
+ usageStats.setLastJobRunTime(job.getSourcePackageName(), job.getSourceUserId(),
+ mExecutionStartTimeElapsed);
+
// Once we'e begun executing a job, we by definition no longer care whether
// it was inflated from disk with not-yet-coherent delay/deadline bounds.
job.clearPersistedUtcTimes();
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index 31c20cbf82f9..28fa86b3a893 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -1348,11 +1348,11 @@ public class LockSettingsService extends ILockSettings.Stub {
.verifyChallenge(userId, 0, willStore.hash, credential.getBytes());
setUserKeyProtection(userId, credential, convertResponse(gkResponse));
fixateNewestUserKeyAuth(userId);
- mRecoverableKeyStoreManager.lockScreenSecretChanged(credentialType, credential,
- userId);
// Refresh the auth token
doVerifyCredential(credential, credentialType, true, 0, userId, null /* progressCallback */);
synchronizeUnifiedWorkChallengeForProfiles(userId, null);
+ mRecoverableKeyStoreManager.lockScreenSecretChanged(credentialType, credential,
+ userId);
} else {
throw new RemoteException("Failed to enroll " +
(credentialType == LockPatternUtils.CREDENTIAL_TYPE_PASSWORD ? "password"
@@ -1982,8 +1982,8 @@ public class LockSettingsService extends ILockSettings.Stub {
}
@Override
- public KeyChainSnapshot getRecoveryData(@NonNull byte[] account) throws RemoteException {
- return mRecoverableKeyStoreManager.getRecoveryData(account);
+ public KeyChainSnapshot getKeyChainSnapshot() throws RemoteException {
+ return mRecoverableKeyStoreManager.getKeyChainSnapshot();
}
public void setSnapshotCreatedPendingIntent(@Nullable PendingIntent intent)
@@ -2494,6 +2494,7 @@ public class LockSettingsService extends ILockSettings.Stub {
(response != null ? "rate limit exceeded" : "failed"));
return;
}
+ mRecoverableKeyStoreManager.lockScreenSecretChanged(credentialType, credential, userId);
}
@Override
diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncTask.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncTask.java
index db46c3d4df3d..662ffc814390 100644
--- a/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncTask.java
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncTask.java
@@ -72,7 +72,7 @@ public class KeySyncTask implements Runnable {
private final int mCredentialType;
private final String mCredential;
private final boolean mCredentialUpdated;
- private final PlatformKeyManager.Factory mPlatformKeyManagerFactory;
+ private final PlatformKeyManager mPlatformKeyManager;
private final RecoverySnapshotStorage mRecoverySnapshotStorage;
private final RecoverySnapshotListenersStorage mSnapshotListenersStorage;
@@ -94,7 +94,7 @@ public class KeySyncTask implements Runnable {
credentialType,
credential,
credentialUpdated,
- () -> PlatformKeyManager.getInstance(context, recoverableKeyStoreDb));
+ PlatformKeyManager.getInstance(context, recoverableKeyStoreDb));
}
/**
@@ -105,9 +105,7 @@ public class KeySyncTask implements Runnable {
* @param credentialType The type of credential as defined in {@code LockPatternUtils}
* @param credential The credential, encoded as a {@link String}.
* @param credentialUpdated signals weather credentials were updated.
- * @param platformKeyManagerFactory Instantiates a {@link PlatformKeyManager} for the user.
- * This is a factory to enable unit testing, as otherwise it would be impossible to test
- * without a screen unlock occurring!
+ * @param platformKeyManager platform key manager
*/
@VisibleForTesting
KeySyncTask(
@@ -118,14 +116,14 @@ public class KeySyncTask implements Runnable {
int credentialType,
String credential,
boolean credentialUpdated,
- PlatformKeyManager.Factory platformKeyManagerFactory) {
+ PlatformKeyManager platformKeyManager) {
mSnapshotListenersStorage = recoverySnapshotListenersStorage;
mRecoverableKeyStoreDb = recoverableKeyStoreDb;
mUserId = userId;
mCredentialType = credentialType;
mCredential = credential;
mCredentialUpdated = credentialUpdated;
- mPlatformKeyManagerFactory = platformKeyManagerFactory;
+ mPlatformKeyManager = platformKeyManager;
mRecoverySnapshotStorage = snapshotStorage;
}
@@ -145,6 +143,8 @@ public class KeySyncTask implements Runnable {
if (mCredentialType == LockPatternUtils.CREDENTIAL_TYPE_NONE) {
// Application keys for the user will not be available for sync.
Log.w(TAG, "Credentials are not set for user " + mUserId);
+ int generation = mPlatformKeyManager.getGenerationId(mUserId);
+ mPlatformKeyManager.invalidatePlatformKey(mUserId, generation);
return;
}
@@ -158,9 +158,17 @@ public class KeySyncTask implements Runnable {
}
private void syncKeysForAgent(int recoveryAgentUid) {
+ boolean recreateCurrentVersion = false;
if (!shoudCreateSnapshot(recoveryAgentUid)) {
- Log.d(TAG, "Key sync not needed.");
- return;
+ recreateCurrentVersion =
+ (mRecoverableKeyStoreDb.getSnapshotVersion(mUserId, recoveryAgentUid) != null)
+ && (mRecoverySnapshotStorage.get(recoveryAgentUid) == null);
+ if (recreateCurrentVersion) {
+ Log.d(TAG, "Recreating most recent snapshot");
+ } else {
+ Log.d(TAG, "Key sync not needed.");
+ return;
+ }
}
if (!mSnapshotListenersStorage.hasListener(recoveryAgentUid)) {
@@ -253,23 +261,21 @@ public class KeySyncTask implements Runnable {
Log.e(TAG,"Could not encrypt with recovery key", e);
return;
}
- // TODO: store raw data in RecoveryServiceMetadataEntry and generate Parcelables later
- // TODO: use Builder.
- KeyChainProtectionParams metadata = new KeyChainProtectionParams(
- /*userSecretType=*/ TYPE_LOCKSCREEN,
- /*lockScreenUiFormat=*/ getUiFormat(mCredentialType, mCredential),
- /*keyDerivationParams=*/ KeyDerivationParams.createSha256Params(salt),
- /*secret=*/ new byte[0]);
+ KeyChainProtectionParams metadata = new KeyChainProtectionParams.Builder()
+ .setUserSecretType(TYPE_LOCKSCREEN)
+ .setLockScreenUiFormat(getUiFormat(mCredentialType, mCredential))
+ .setKeyDerivationParams(KeyDerivationParams.createSha256Params(salt))
+ .setSecret(new byte[0])
+ .build();
+
ArrayList<KeyChainProtectionParams> metadataList = new ArrayList<>();
metadataList.add(metadata);
- int snapshotVersion = incrementSnapshotVersion(recoveryAgentUid);
-
// If application keys are not updated, snapshot will not be created on next unlock.
mRecoverableKeyStoreDb.setShouldCreateSnapshot(mUserId, recoveryAgentUid, false);
mRecoverySnapshotStorage.put(recoveryAgentUid, new KeyChainSnapshot.Builder()
- .setSnapshotVersion(snapshotVersion)
+ .setSnapshotVersion(getSnapshotVersion(recoveryAgentUid, recreateCurrentVersion))
.setMaxAttempts(TRUSTED_HARDWARE_MAX_ATTEMPTS)
.setCounterId(counterId)
.setTrustedHardwarePublicKey(SecureBox.encodePublicKey(publicKey))
@@ -283,9 +289,14 @@ public class KeySyncTask implements Runnable {
}
@VisibleForTesting
- int incrementSnapshotVersion(int recoveryAgentUid) {
+ int getSnapshotVersion(int recoveryAgentUid, boolean recreateCurrentVersion) {
Long snapshotVersion = mRecoverableKeyStoreDb.getSnapshotVersion(mUserId, recoveryAgentUid);
- snapshotVersion = snapshotVersion == null ? 1 : snapshotVersion + 1;
+ if (recreateCurrentVersion) {
+ // version shouldn't be null at this moment.
+ snapshotVersion = snapshotVersion == null ? 1 : snapshotVersion;
+ } else {
+ snapshotVersion = snapshotVersion == null ? 1 : snapshotVersion + 1;
+ }
mRecoverableKeyStoreDb.setSnapshotVersion(mUserId, recoveryAgentUid, snapshotVersion);
return snapshotVersion.intValue();
@@ -304,8 +315,7 @@ public class KeySyncTask implements Runnable {
throws InsecureUserException, KeyStoreException, UnrecoverableKeyException,
NoSuchAlgorithmException, NoSuchPaddingException, BadPlatformKeyException,
InvalidKeyException, InvalidAlgorithmParameterException {
- PlatformKeyManager platformKeyManager = mPlatformKeyManagerFactory.newInstance();
- PlatformDecryptionKey decryptKey = platformKeyManager.getDecryptKey(mUserId);;
+ PlatformDecryptionKey decryptKey = mPlatformKeyManager.getDecryptKey(mUserId);;
Map<String, WrappedKey> wrappedKeys = mRecoverableKeyStoreDb.getAllKeys(
mUserId, recoveryAgentUid, decryptKey.getGenerationId());
return WrappedKey.unwrapKeys(decryptKey, wrappedKeys);
@@ -414,10 +424,10 @@ public class KeySyncTask implements Runnable {
Map<String, byte[]> encryptedApplicationKeys) {
ArrayList<WrappedApplicationKey> keyEntries = new ArrayList<>();
for (String alias : encryptedApplicationKeys.keySet()) {
- keyEntries.add(
- new WrappedApplicationKey(
- alias,
- encryptedApplicationKeys.get(alias)));
+ keyEntries.add(new WrappedApplicationKey.Builder()
+ .setAlias(alias)
+ .setEncryptedKeyMaterial(encryptedApplicationKeys.get(alias))
+ .build());
}
return keyEntries;
}
diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/PlatformKeyManager.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/PlatformKeyManager.java
index ee6a89312988..3a78f950675e 100644
--- a/services/core/java/com/android/server/locksettings/recoverablekeystore/PlatformKeyManager.java
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/PlatformKeyManager.java
@@ -129,6 +129,26 @@ public class PlatformKeyManager {
}
/**
+ * Removes the platform key from Android KeyStore.
+ * It is triggered when user disables lock screen.
+ *
+ * @param userId The ID of the user to whose lock screen the platform key must be bound.
+ * @param generationId Generation id.
+ *
+ * @hide
+ */
+ public void invalidatePlatformKey(int userId, int generationId) {
+ if (generationId != -1) {
+ try {
+ mKeyStore.deleteEntry(getEncryptAlias(userId, generationId));
+ mKeyStore.deleteEntry(getDecryptAlias(userId, generationId));
+ } catch (KeyStoreException e) {
+ // Ignore failed attempt to delete key.
+ }
+ }
+ }
+
+ /**
* Generates a new key and increments the generation ID. Should be invoked if the platform key
* is corrupted and needs to be rotated.
* Updates status of old keys to {@code RecoveryController.RECOVERY_STATUS_PERMANENT_FAILURE}.
@@ -152,6 +172,7 @@ public class PlatformKeyManager {
if (generationId == -1) {
nextId = 1;
} else {
+ invalidatePlatformKey(userId, generationId);
nextId = generationId + 1;
}
generateAndLoadKey(userId, nextId);
@@ -197,8 +218,12 @@ public class PlatformKeyManager {
private PlatformEncryptionKey getEncryptKeyInternal(int userId) throws KeyStoreException,
UnrecoverableKeyException, NoSuchAlgorithmException, InsecureUserException {
int generationId = getGenerationId(userId);
+ String alias = getEncryptAlias(userId, generationId);
+ if (!mKeyStore.containsAlias(alias)) {
+ throw new UnrecoverableKeyException("KeyStore doesn't contain key " + alias);
+ }
AndroidKeyStoreSecretKey key = (AndroidKeyStoreSecretKey) mKeyStore.getKey(
- getEncryptAlias(userId, generationId), /*password=*/ null);
+ alias, /*password=*/ null);
return new PlatformEncryptionKey(generationId, key);
}
@@ -242,8 +267,12 @@ public class PlatformKeyManager {
private PlatformDecryptionKey getDecryptKeyInternal(int userId) throws KeyStoreException,
UnrecoverableKeyException, NoSuchAlgorithmException, InsecureUserException {
int generationId = getGenerationId(userId);
+ String alias = getDecryptAlias(userId, generationId);
+ if (!mKeyStore.containsAlias(alias)) {
+ throw new UnrecoverableKeyException("KeyStore doesn't contain key " + alias);
+ }
AndroidKeyStoreSecretKey key = (AndroidKeyStoreSecretKey) mKeyStore.getKey(
- getDecryptAlias(userId, generationId), /*password=*/ null);
+ alias, /*password=*/ null);
return new PlatformDecryptionKey(generationId, key);
}
@@ -405,16 +434,4 @@ public class PlatformKeyManager {
return keyStore;
}
- /**
- * @hide
- */
- public interface Factory {
- /**
- * New PlatformKeyManager instance.
- *
- * @hide
- */
- PlatformKeyManager newInstance()
- throws NoSuchAlgorithmException, InsecureUserException, KeyStoreException;
- }
}
diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java
index 0d567d1e971d..37117e3c2a0f 100644
--- a/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java
@@ -171,7 +171,7 @@ public class RecoverableKeyStoreManager {
* @hide
*/
public @NonNull
- KeyChainSnapshot getRecoveryData(@NonNull byte[] account)
+ KeyChainSnapshot getKeyChainSnapshot()
throws RemoteException {
checkRecoverKeyStorePermission();
int uid = Binder.getCallingUid();
@@ -579,6 +579,7 @@ public class RecoverableKeyStoreManager {
/**
* This function can only be used inside LockSettingsService.
+ *
* @param storedHashType from {@code CredentialHash}
* @param credential - unencrypted String
* @param userId for the user whose lock screen credentials were changed.
@@ -604,7 +605,7 @@ public class RecoverableKeyStoreManager {
} catch (KeyStoreException e) {
Log.e(TAG, "Key store error encountered during recoverable key sync", e);
} catch (InsecureUserException e) {
- Log.wtf(TAG, "Impossible - insecure user, but user just entered lock screen", e);
+ Log.e(TAG, "InsecureUserException during lock screen secret update", e);
}
}
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 4c9da8949cc9..5e3d77874e9b 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -3421,7 +3421,7 @@ public class NotificationManagerService extends SystemService {
long zenLog = proto.start(NotificationServiceDumpProto.ZEN);
mZenModeHelper.dump(proto);
for (ComponentName suppressor : mEffectsSuppressors) {
- proto.write(ZenModeProto.SUPPRESSORS, suppressor.toString());
+ suppressor.writeToProto(proto, ZenModeProto.SUPPRESSORS);
}
proto.end(zenLog);
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index 932e4f948a82..2859613c0047 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -553,16 +553,15 @@ public class ZenModeHelper {
}
void dump(ProtoOutputStream proto) {
-
proto.write(ZenModeProto.ZEN_MODE, mZenMode);
synchronized (mConfig) {
if (mConfig.manualRule != null) {
- proto.write(ZenModeProto.ENABLED_ACTIVE_CONDITIONS, mConfig.manualRule.toString());
+ mConfig.manualRule.writeToProto(proto, ZenModeProto.ENABLED_ACTIVE_CONDITIONS);
}
for (ZenRule rule : mConfig.automaticRules.values()) {
if (rule.enabled && rule.condition.state == Condition.STATE_TRUE
&& !rule.snoozing) {
- proto.write(ZenModeProto.ENABLED_ACTIVE_CONDITIONS, rule.toString());
+ rule.writeToProto(proto, ZenModeProto.ENABLED_ACTIVE_CONDITIONS);
}
}
mConfig.toNotificationPolicy().writeToProto(proto, ZenModeProto.POLICY);
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 776794593512..3049e98099ca 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -441,6 +441,7 @@ public class PackageManagerService extends IPackageManager.Stub
private static final int NFC_UID = Process.NFC_UID;
private static final int BLUETOOTH_UID = Process.BLUETOOTH_UID;
private static final int SHELL_UID = Process.SHELL_UID;
+ private static final int SE_UID = Process.SE_UID;
// Suffix used during package installation when copying/moving
// package apks to install directory.
@@ -2408,6 +2409,8 @@ public class PackageManagerService extends IPackageManager.Stub
ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
mSettings.addSharedUserLPw("android.uid.shell", SHELL_UID,
ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
+ mSettings.addSharedUserLPw("android.uid.se", SE_UID,
+ ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
String separateProcesses = SystemProperties.get("debug.separate_processes");
if (separateProcesses != null && separateProcesses.length() > 0) {
diff --git a/services/core/java/com/android/server/stats/StatsCompanionService.java b/services/core/java/com/android/server/stats/StatsCompanionService.java
index cfdec4cc54bc..e3a6fa3bffc3 100644
--- a/services/core/java/com/android/server/stats/StatsCompanionService.java
+++ b/services/core/java/com/android/server/stats/StatsCompanionService.java
@@ -328,9 +328,11 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
* Skip immediately if intent is not relevant to device shutdown.
*/
if (!intent.getAction().equals(Intent.ACTION_REBOOT)
- && !intent.getAction().equals(Intent.ACTION_SHUTDOWN)) {
- return;
+ && !(intent.getAction().equals(Intent.ACTION_SHUTDOWN)
+ && (intent.getFlags() & Intent.FLAG_RECEIVER_FOREGROUND) != 0)) {
+ return;
}
+
Slog.i(TAG, "StatsCompanionService noticed a shutdown.");
synchronized (sStatsdLock) {
if (sStatsd == null) {
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 99712a5173db..8f6fac0566b9 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -311,6 +311,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
private static final String TAG_PRINTING_ENABLED = "printing-enabled";
+ private static final String TAG_TRANSFER_OWNERSHIP_BUNDLE = "transfer-ownership-bundle";
+
private static final int REQUEST_EXPIRE_PASSWORD = 5571;
private static final long MS_PER_DAY = TimeUnit.DAYS.toMillis(1);
@@ -12624,6 +12626,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
try (FileInputStream stream = new FileInputStream(bundleFile)) {
XmlPullParser parser = Xml.newPullParser();
parser.setInput(stream, null);
+ parser.next();
return PersistableBundle.restoreFromXml(parser);
} catch (IOException | XmlPullParserException | IllegalArgumentException e) {
Slog.e(LOG_TAG, "Caught exception while trying to load the "
@@ -12845,7 +12848,10 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
final XmlSerializer serializer = new FastXmlSerializer();
serializer.setOutput(stream, StandardCharsets.UTF_8.name());
serializer.startDocument(null, true);
+ serializer.startTag(null, TAG_TRANSFER_OWNERSHIP_BUNDLE);
bundle.saveToXml(serializer);
+ serializer.endTag(null, TAG_TRANSFER_OWNERSHIP_BUNDLE);
+ serializer.endDocument();
atomicFile.finishWrite(stream);
} catch (IOException | XmlPullParserException e) {
Slog.e(LOG_TAG, "Caught exception while trying to save the "
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java
index 6a3a260361c9..ce5ee138cc3d 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java
@@ -121,7 +121,7 @@ public class KeySyncTaskTest {
TEST_CREDENTIAL_TYPE,
TEST_CREDENTIAL,
/*credentialUpdated=*/ false,
- () -> mPlatformKeyManager);
+ mPlatformKeyManager);
mWrappingKey = generateAndroidKeyStoreKey();
mEncryptKey = new PlatformEncryptionKey(TEST_GENERATION_ID, mWrappingKey);
@@ -327,8 +327,7 @@ public class KeySyncTaskTest {
mRecoverableKeyStoreDb.setRecoveryServicePublicKey(
TEST_USER_ID, TEST_RECOVERY_AGENT_UID, mKeyPair.getPublic());
when(mSnapshotListenersStorage.hasListener(TEST_RECOVERY_AGENT_UID)).thenReturn(true);
- SecretKey applicationKey =
- addApplicationKey(TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_APP_KEY_ALIAS);
+ addApplicationKey(TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_APP_KEY_ALIAS);
mKeySyncTask.run();
@@ -343,6 +342,26 @@ public class KeySyncTaskTest {
}
@Test
+ public void run_recreatesMissingSnapshot() throws Exception {
+ mRecoverableKeyStoreDb.setRecoveryServicePublicKey(
+ TEST_USER_ID, TEST_RECOVERY_AGENT_UID, mKeyPair.getPublic());
+ when(mSnapshotListenersStorage.hasListener(TEST_RECOVERY_AGENT_UID)).thenReturn(true);
+ addApplicationKey(TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_APP_KEY_ALIAS);
+
+ mKeySyncTask.run();
+
+ KeyChainSnapshot keyChainSnapshot = mRecoverySnapshotStorage.get(TEST_RECOVERY_AGENT_UID);
+ assertThat(keyChainSnapshot.getSnapshotVersion()).isEqualTo(1); // default value;
+
+ mRecoverySnapshotStorage.remove(TEST_RECOVERY_AGENT_UID); // corrupt snapshot.
+
+ mKeySyncTask.run();
+
+ keyChainSnapshot = mRecoverySnapshotStorage.get(TEST_RECOVERY_AGENT_UID);
+ assertThat(keyChainSnapshot.getSnapshotVersion()).isEqualTo(1); // Same version
+ }
+
+ @Test
public void run_setsCorrectTypeForPassword() throws Exception {
mKeySyncTask = new KeySyncTask(
mRecoverableKeyStoreDb,
@@ -352,7 +371,7 @@ public class KeySyncTaskTest {
CREDENTIAL_TYPE_PASSWORD,
"password",
/*credentialUpdated=*/ false,
- () -> mPlatformKeyManager);
+ mPlatformKeyManager);
mRecoverableKeyStoreDb.setRecoveryServicePublicKey(
TEST_USER_ID, TEST_RECOVERY_AGENT_UID, mKeyPair.getPublic());
@@ -378,7 +397,7 @@ public class KeySyncTaskTest {
CREDENTIAL_TYPE_PASSWORD,
/*credential=*/ "1234",
/*credentialUpdated=*/ false,
- () -> mPlatformKeyManager);
+ mPlatformKeyManager);
mRecoverableKeyStoreDb.setRecoveryServicePublicKey(
TEST_USER_ID, TEST_RECOVERY_AGENT_UID, mKeyPair.getPublic());
@@ -405,7 +424,7 @@ public class KeySyncTaskTest {
CREDENTIAL_TYPE_PATTERN,
"12345",
/*credentialUpdated=*/ false,
- () -> mPlatformKeyManager);
+ mPlatformKeyManager);
mRecoverableKeyStoreDb.setRecoveryServicePublicKey(
TEST_USER_ID, TEST_RECOVERY_AGENT_UID, mKeyPair.getPublic());
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/PlatformKeyManagerTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/PlatformKeyManagerTest.java
index 6fc9e082bb7c..f9ffccdd5d38 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/PlatformKeyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/PlatformKeyManagerTest.java
@@ -252,6 +252,10 @@ public class PlatformKeyManagerTest {
@Test
public void getDecryptKey_getsDecryptKeyWithCorrectAlias() throws Exception {
+ when(mKeyStoreProxy
+ .containsAlias("com.android.server.locksettings.recoverablekeystore/"
+ + "platform/42/1/decrypt")).thenReturn(true);
+
mPlatformKeyManager.getDecryptKey(USER_ID_FIXTURE);
verify(mKeyStoreProxy).getKey(
@@ -265,6 +269,13 @@ public class PlatformKeyManagerTest {
eq("com.android.server.locksettings.recoverablekeystore/platform/42/1/encrypt"),
any());
+ when(mKeyStoreProxy
+ .containsAlias("com.android.server.locksettings.recoverablekeystore/"
+ + "platform/42/1/encrypt")).thenReturn(true);
+ when(mKeyStoreProxy
+ .containsAlias("com.android.server.locksettings.recoverablekeystore/"
+ + "platform/42/2/encrypt")).thenReturn(true);
+
mPlatformKeyManager.getEncryptKey(USER_ID_FIXTURE);
verify(mKeyStoreProxy).getKey(
@@ -282,19 +293,50 @@ public class PlatformKeyManagerTest {
eq("com.android.server.locksettings.recoverablekeystore/platform/42/1/decrypt"),
any());
+ when(mKeyStoreProxy
+ .containsAlias("com.android.server.locksettings.recoverablekeystore/"
+ + "platform/42/1/decrypt")).thenReturn(false); // was removed.
+
+ when(mKeyStoreProxy
+ .containsAlias("com.android.server.locksettings.recoverablekeystore/"
+ + "platform/42/2/decrypt")).thenReturn(true); // new version is available
+
mPlatformKeyManager.getDecryptKey(USER_ID_FIXTURE);
+ verify(mKeyStoreProxy).containsAlias(
+ eq("com.android.server.locksettings.recoverablekeystore/platform/42/1/decrypt"));
+ // Attempt to get regenerated key.
verify(mKeyStoreProxy).getKey(
- eq("com.android.server.locksettings.recoverablekeystore/platform/42/1/decrypt"),
+ eq("com.android.server.locksettings.recoverablekeystore/platform/42/2/decrypt"),
any());
+ }
+
+ @Test
+ public void getEncryptKey_generatesNewKeyIfOldWasRemoved() throws Exception {
+ when(mKeyStoreProxy
+ .containsAlias("com.android.server.locksettings.recoverablekeystore/"
+ + "platform/42/1/encrypt")).thenReturn(false); // was removed.
+
+ when(mKeyStoreProxy
+ .containsAlias("com.android.server.locksettings.recoverablekeystore/"
+ + "platform/42/2/encrypt")).thenReturn(true); // new version is available
+
+ mPlatformKeyManager.getEncryptKey(USER_ID_FIXTURE);
+
+ verify(mKeyStoreProxy).containsAlias(
+ eq("com.android.server.locksettings.recoverablekeystore/platform/42/1/encrypt"));
// Attempt to get regenerated key.
verify(mKeyStoreProxy).getKey(
- eq("com.android.server.locksettings.recoverablekeystore/platform/42/2/decrypt"),
+ eq("com.android.server.locksettings.recoverablekeystore/platform/42/2/encrypt"),
any());
}
@Test
- public void getEncryptKey_getsDecryptKeyWithCorrectAlias() throws Exception {
+ public void getEncryptKey_getsEndryptKeyWithCorrectAlias() throws Exception {
+ when(mKeyStoreProxy
+ .containsAlias("com.android.server.locksettings.recoverablekeystore/"
+ + "platform/42/1/encrypt")).thenReturn(true);
+
mPlatformKeyManager.getEncryptKey(USER_ID_FIXTURE);
verify(mKeyStoreProxy).getKey(
@@ -312,6 +354,26 @@ public class PlatformKeyManagerTest {
}
@Test
+ public void regenerate_deletesOldKeysFromKeystore() throws Exception {
+ mPlatformKeyManager.init(USER_ID_FIXTURE);
+
+ mPlatformKeyManager.regenerate(USER_ID_FIXTURE);
+
+ verify(mKeyStoreProxy).deleteEntry(
+ eq("com.android.server.locksettings.recoverablekeystore/platform/42/1/encrypt"));
+ verify(mKeyStoreProxy).deleteEntry(
+ eq("com.android.server.locksettings.recoverablekeystore/platform/42/1/decrypt"));
+
+ mPlatformKeyManager.regenerate(USER_ID_FIXTURE);
+
+ // Removes second generation keys.
+ verify(mKeyStoreProxy).deleteEntry(
+ eq("com.android.server.locksettings.recoverablekeystore/platform/42/2/encrypt"));
+ verify(mKeyStoreProxy).deleteEntry(
+ eq("com.android.server.locksettings.recoverablekeystore/platform/42/2/decrypt"));
+ }
+
+ @Test
public void regenerate_generatesANewEncryptKeyWithTheCorrectAlias() throws Exception {
mPlatformKeyManager.init(USER_ID_FIXTURE);
diff --git a/services/tests/servicestests/src/com/android/server/net/ConnOnActivityStartTest.java b/services/tests/servicestests/src/com/android/server/net/ConnOnActivityStartTest.java
index c7fa62e56380..376db5bbad67 100644
--- a/services/tests/servicestests/src/com/android/server/net/ConnOnActivityStartTest.java
+++ b/services/tests/servicestests/src/com/android/server/net/ConnOnActivityStartTest.java
@@ -388,7 +388,8 @@ public class ConnOnActivityStartTest {
latch.countDown();
}
});
- launchIntent.putExtras(extras);
+ launchIntent.putExtras(extras)
+ .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mContext.startActivity(launchIntent);
if (latch.await(NETWORK_CHECK_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
if (errors[0] != null) {
diff --git a/services/usage/java/com/android/server/usage/AppIdleHistory.java b/services/usage/java/com/android/server/usage/AppIdleHistory.java
index 0cbda2845e53..2becdf230dbc 100644
--- a/services/usage/java/com/android/server/usage/AppIdleHistory.java
+++ b/services/usage/java/com/android/server/usage/AppIdleHistory.java
@@ -36,6 +36,8 @@ import android.util.Xml;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.IndentingPrintWriter;
+import com.android.server.LocalServices;
+import com.android.server.job.JobSchedulerInternal;
import libcore.io.IoUtils;
@@ -202,27 +204,23 @@ public class AppIdleHistory {
* that's in the future, then the usage event is temporary and keeps the app in the specified
* bucket at least until the timeout is reached. This can be used to keep the app in an
* elevated bucket for a while until some important task gets to run.
- * @param packageName
- * @param userId
- * @param bucket the bucket to set the app to
+ * @param appUsageHistory the usage record for the app being updated
+ * @param packageName name of the app being updated, for logging purposes
+ * @param newBucket the bucket to set the app to
* @param elapsedRealtime mark as used time if non-zero
* @param timeout set the timeout of the specified bucket, if non-zero
* @return
*/
- public int reportUsage(String packageName, int userId, int bucket, long elapsedRealtime,
- long timeout) {
- ArrayMap<String, AppUsageHistory> userHistory = getUserHistory(userId);
- AppUsageHistory appUsageHistory = getPackageHistory(userHistory, packageName,
- elapsedRealtime, true);
-
+ public AppUsageHistory reportUsage(AppUsageHistory appUsageHistory, String packageName,
+ int newBucket, long elapsedRealtime, long timeout) {
if (elapsedRealtime != 0) {
appUsageHistory.lastUsedElapsedTime = mElapsedDuration
+ (elapsedRealtime - mElapsedSnapshot);
appUsageHistory.lastUsedScreenTime = getScreenOnTime(elapsedRealtime);
}
- if (appUsageHistory.currentBucket > bucket) {
- appUsageHistory.currentBucket = bucket;
+ if (appUsageHistory.currentBucket > newBucket) {
+ appUsageHistory.currentBucket = newBucket;
if (DEBUG) {
Slog.d(TAG, "Moved " + packageName + " to bucket=" + appUsageHistory
.currentBucket
@@ -235,7 +233,26 @@ public class AppIdleHistory {
}
appUsageHistory.bucketingReason = REASON_USAGE;
- return appUsageHistory.currentBucket;
+ return appUsageHistory;
+ }
+
+ /**
+ * Mark the app as used and update the bucket if necessary. If there is a timeout specified
+ * that's in the future, then the usage event is temporary and keeps the app in the specified
+ * bucket at least until the timeout is reached. This can be used to keep the app in an
+ * elevated bucket for a while until some important task gets to run.
+ * @param packageName
+ * @param userId
+ * @param newBucket the bucket to set the app to
+ * @param elapsedRealtime mark as used time if non-zero
+ * @param timeout set the timeout of the specified bucket, if non-zero
+ * @return
+ */
+ public AppUsageHistory reportUsage(String packageName, int userId, int newBucket,
+ long nowElapsed, long timeout) {
+ ArrayMap<String, AppUsageHistory> userHistory = getUserHistory(userId);
+ AppUsageHistory history = getPackageHistory(userHistory, packageName, nowElapsed, true);
+ return reportUsage(history, packageName, newBucket, nowElapsed, timeout);
}
private ArrayMap<String, AppUsageHistory> getUserHistory(int userId) {
diff --git a/services/usage/java/com/android/server/usage/AppStandbyController.java b/services/usage/java/com/android/server/usage/AppStandbyController.java
index 6782188c0f34..8cb2eecc654a 100644
--- a/services/usage/java/com/android/server/usage/AppStandbyController.java
+++ b/services/usage/java/com/android/server/usage/AppStandbyController.java
@@ -27,7 +27,6 @@ import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_FREQUENT;
import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_NEVER;
import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_RARE;
import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_WORKING_SET;
-
import static com.android.server.SystemService.PHASE_BOOT_COMPLETED;
import static com.android.server.SystemService.PHASE_SYSTEM_SERVICES_READY;
@@ -81,6 +80,7 @@ import com.android.internal.util.ArrayUtils;
import com.android.internal.util.ConcurrentUtils;
import com.android.internal.util.IndentingPrintWriter;
import com.android.server.LocalServices;
+import com.android.server.usage.AppIdleHistory.AppUsageHistory;
import java.io.File;
import java.io.PrintWriter;
@@ -198,6 +198,48 @@ public class AppStandbyController {
private PackageManager mPackageManager;
Injector mInjector;
+ static final ArrayList<StandbyUpdateRecord> sStandbyUpdatePool = new ArrayList<>(4);
+
+ public static class StandbyUpdateRecord {
+ // Identity of the app whose standby state has changed
+ String packageName;
+ int userId;
+
+ // What the standby bucket the app is now in
+ int bucket;
+
+ // Whether the bucket change is because the user has started interacting with the app
+ boolean isUserInteraction;
+
+ StandbyUpdateRecord(String pkgName, int userId, int bucket, boolean isInteraction) {
+ this.packageName = pkgName;
+ this.userId = userId;
+ this.bucket = bucket;
+ this.isUserInteraction = isInteraction;
+ }
+
+ public static StandbyUpdateRecord obtain(String pkgName, int userId,
+ int bucket, boolean isInteraction) {
+ synchronized (sStandbyUpdatePool) {
+ final int size = sStandbyUpdatePool.size();
+ if (size < 1) {
+ return new StandbyUpdateRecord(pkgName, userId, bucket, isInteraction);
+ }
+ StandbyUpdateRecord r = sStandbyUpdatePool.remove(size - 1);
+ r.packageName = pkgName;
+ r.userId = userId;
+ r.bucket = bucket;
+ r.isUserInteraction = isInteraction;
+ return r;
+ }
+ }
+
+ public void recycle() {
+ synchronized (sStandbyUpdatePool) {
+ sStandbyUpdatePool.add(this);
+ }
+ }
+ }
AppStandbyController(Context context, Looper looper) {
this(new Injector(context, looper));
@@ -279,11 +321,11 @@ public class AppStandbyController {
}
if (!packageName.equals(providerPkgName)) {
synchronized (mAppIdleLock) {
- int newBucket = mAppIdleHistory.reportUsage(packageName, userId,
+ AppUsageHistory appUsage = mAppIdleHistory.reportUsage(packageName, userId,
STANDBY_BUCKET_ACTIVE, elapsedRealtime,
elapsedRealtime + 2 * ONE_HOUR);
maybeInformListeners(packageName, userId, elapsedRealtime,
- newBucket);
+ appUsage.currentBucket, false);
}
}
} catch (PackageManager.NameNotFoundException e) {
@@ -417,7 +459,7 @@ public class AppStandbyController {
STANDBY_BUCKET_EXEMPTED, REASON_DEFAULT);
}
maybeInformListeners(packageName, userId, elapsedRealtime,
- STANDBY_BUCKET_EXEMPTED);
+ STANDBY_BUCKET_EXEMPTED, false);
} else {
synchronized (mAppIdleLock) {
AppIdleHistory.AppUsageHistory app =
@@ -446,7 +488,7 @@ public class AppStandbyController {
mAppIdleHistory.setAppStandbyBucket(packageName, userId,
elapsedRealtime, newBucket, REASON_TIMEOUT);
maybeInformListeners(packageName, userId, elapsedRealtime,
- newBucket);
+ newBucket, false);
}
}
}
@@ -474,13 +516,16 @@ public class AppStandbyController {
}
private void maybeInformListeners(String packageName, int userId,
- long elapsedRealtime, int bucket) {
+ long elapsedRealtime, int bucket, boolean userStartedInteracting) {
synchronized (mAppIdleLock) {
// TODO: fold these into one call + lookup for efficiency if needed
if (mAppIdleHistory.shouldInformListeners(packageName, userId,
elapsedRealtime, bucket)) {
+ StandbyUpdateRecord r = StandbyUpdateRecord.obtain(packageName, userId,
+ bucket, userStartedInteracting);
mHandler.sendMessage(mHandler.obtainMessage(MSG_INFORM_LISTENERS,
- userId, bucket, packageName));
+ StandbyUpdateRecord.obtain(packageName, userId,
+ bucket, userStartedInteracting)));
}
}
}
@@ -566,19 +611,27 @@ public class AppStandbyController {
|| event.mEventType == UsageEvents.Event.USER_INTERACTION
|| event.mEventType == UsageEvents.Event.NOTIFICATION_SEEN)) {
- final int newBucket;
+ final AppUsageHistory appHistory = mAppIdleHistory.getAppUsageHistory(
+ event.mPackage, userId, elapsedRealtime);
+ final int prevBucket = appHistory.currentBucket;
+ final String prevBucketReason = appHistory.bucketingReason;
if (event.mEventType == UsageEvents.Event.NOTIFICATION_SEEN) {
- newBucket = mAppIdleHistory.reportUsage(event.mPackage, userId,
+ mAppIdleHistory.reportUsage(appHistory, event.mPackage,
STANDBY_BUCKET_WORKING_SET,
elapsedRealtime, elapsedRealtime + 2 * ONE_HOUR);
} else {
- newBucket = mAppIdleHistory.reportUsage(event.mPackage, userId,
+ mAppIdleHistory.reportUsage(event.mPackage, userId,
STANDBY_BUCKET_ACTIVE,
elapsedRealtime, elapsedRealtime + 2 * ONE_HOUR);
}
+ final boolean userStartedInteracting =
+ appHistory.currentBucket == STANDBY_BUCKET_ACTIVE &&
+ prevBucket != appHistory.currentBucket &&
+ prevBucketReason != REASON_USAGE;
maybeInformListeners(event.mPackage, userId, elapsedRealtime,
- newBucket);
+ appHistory.currentBucket, userStartedInteracting);
+
if (previouslyIdle) {
notifyBatteryStats(event.mPackage, userId, false);
}
@@ -611,7 +664,7 @@ public class AppStandbyController {
userId, elapsedRealtime);
// Inform listeners if necessary
if (previouslyIdle != stillIdle) {
- maybeInformListeners(packageName, userId, elapsedRealtime, standbyBucket);
+ maybeInformListeners(packageName, userId, elapsedRealtime, standbyBucket, false);
if (!stillIdle) {
notifyBatteryStats(packageName, userId, idle);
}
@@ -871,8 +924,7 @@ public class AppStandbyController {
mAppIdleHistory.setAppStandbyBucket(packageName, userId, elapsedRealtime, newBucket,
reason);
}
- maybeInformListeners(packageName, userId, elapsedRealtime,
- newBucket);
+ maybeInformListeners(packageName, userId, elapsedRealtime, newBucket, false);
}
@VisibleForTesting
@@ -972,11 +1024,14 @@ public class AppStandbyController {
return packageName != null && packageName.equals(activeScorer);
}
- void informListeners(String packageName, int userId, int bucket) {
+ void informListeners(String packageName, int userId, int bucket, boolean userInteraction) {
final boolean idle = bucket >= STANDBY_BUCKET_RARE;
synchronized (mPackageAccessListeners) {
for (AppIdleStateChangeListener listener : mPackageAccessListeners) {
listener.onAppIdleStateChanged(packageName, userId, idle, bucket);
+ if (userInteraction) {
+ listener.onUserInteractionStarted(packageName, userId);
+ }
}
}
}
@@ -1230,7 +1285,9 @@ public class AppStandbyController {
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_INFORM_LISTENERS:
- informListeners((String) msg.obj, msg.arg1, msg.arg2);
+ StandbyUpdateRecord r = (StandbyUpdateRecord) msg.obj;
+ informListeners(r.packageName, r.userId, r.bucket, r.isUserInteraction);
+ r.recycle();
break;
case MSG_FORCE_IDLE_STATE:
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index 096fdcc24030..36a2a95dd1e1 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -1043,6 +1043,12 @@ public class UsageStatsService extends SystemService implements
return mAppStandby.getTimeSinceLastJobRun(packageName, userId);
}
+ @Override
+ public void reportAppJobState(String packageName, int userId,
+ int numDeferredJobs, long timeSinceLastJobRun) {
+ }
+
+ @Override
public void onActiveAdminAdded(String packageName, int userId) {
mAppStandby.addActiveDeviceAdmin(packageName, userId);
}
diff --git a/telephony/java/android/telephony/data/DataService.java b/telephony/java/android/telephony/data/DataService.java
index fa19ea069044..c4f9022c31ce 100644
--- a/telephony/java/android/telephony/data/DataService.java
+++ b/telephony/java/android/telephony/data/DataService.java
@@ -86,15 +86,17 @@ public abstract class DataService extends Service {
/** The reason of the data request is IWLAN handover */
public static final int REQUEST_REASON_HANDOVER = 3;
- private static final int DATA_SERVICE_INTERNAL_REQUEST_INITIALIZE_SERVICE = 1;
- private static final int DATA_SERVICE_REQUEST_SETUP_DATA_CALL = 2;
- private static final int DATA_SERVICE_REQUEST_DEACTIVATE_DATA_CALL = 3;
- private static final int DATA_SERVICE_REQUEST_SET_INITIAL_ATTACH_APN = 4;
- private static final int DATA_SERVICE_REQUEST_SET_DATA_PROFILE = 5;
- private static final int DATA_SERVICE_REQUEST_GET_DATA_CALL_LIST = 6;
- private static final int DATA_SERVICE_REQUEST_REGISTER_DATA_CALL_LIST_CHANGED = 7;
- private static final int DATA_SERVICE_REQUEST_UNREGISTER_DATA_CALL_LIST_CHANGED = 8;
- private static final int DATA_SERVICE_INDICATION_DATA_CALL_LIST_CHANGED = 9;
+ private static final int DATA_SERVICE_CREATE_DATA_SERVICE_PROVIDER = 1;
+ private static final int DATA_SERVICE_REMOVE_DATA_SERVICE_PROVIDER = 2;
+ private static final int DATA_SERVICE_REMOVE_ALL_DATA_SERVICE_PROVIDERS = 3;
+ private static final int DATA_SERVICE_REQUEST_SETUP_DATA_CALL = 4;
+ private static final int DATA_SERVICE_REQUEST_DEACTIVATE_DATA_CALL = 5;
+ private static final int DATA_SERVICE_REQUEST_SET_INITIAL_ATTACH_APN = 6;
+ private static final int DATA_SERVICE_REQUEST_SET_DATA_PROFILE = 7;
+ private static final int DATA_SERVICE_REQUEST_GET_DATA_CALL_LIST = 8;
+ private static final int DATA_SERVICE_REQUEST_REGISTER_DATA_CALL_LIST_CHANGED = 9;
+ private static final int DATA_SERVICE_REQUEST_UNREGISTER_DATA_CALL_LIST_CHANGED = 10;
+ private static final int DATA_SERVICE_INDICATION_DATA_CALL_LIST_CHANGED = 11;
private final HandlerThread mHandlerThread;
@@ -102,7 +104,7 @@ public abstract class DataService extends Service {
private final SparseArray<DataServiceProvider> mServiceMap = new SparseArray<>();
- private final SparseArray<IDataServiceWrapper> mBinderMap = new SparseArray<>();
+ private final IBinder mBinder = new IDataServiceWrapper();
/**
* The abstract class of the actual data service implementation. The data service provider
@@ -321,23 +323,34 @@ public abstract class DataService extends Service {
public void handleMessage(Message message) {
IDataServiceCallback callback;
final int slotId = message.arg1;
- DataServiceProvider service;
-
- synchronized (mServiceMap) {
- service = mServiceMap.get(slotId);
- }
+ DataServiceProvider serviceProvider = mServiceMap.get(slotId);
switch (message.what) {
- case DATA_SERVICE_INTERNAL_REQUEST_INITIALIZE_SERVICE:
- service = createDataServiceProvider(message.arg1);
- if (service != null) {
- mServiceMap.put(slotId, service);
+ case DATA_SERVICE_CREATE_DATA_SERVICE_PROVIDER:
+ serviceProvider = createDataServiceProvider(message.arg1);
+ if (serviceProvider != null) {
+ mServiceMap.put(slotId, serviceProvider);
}
break;
+ case DATA_SERVICE_REMOVE_DATA_SERVICE_PROVIDER:
+ if (serviceProvider != null) {
+ serviceProvider.onDestroy();
+ mServiceMap.remove(slotId);
+ }
+ break;
+ case DATA_SERVICE_REMOVE_ALL_DATA_SERVICE_PROVIDERS:
+ for (int i = 0; i < mServiceMap.size(); i++) {
+ serviceProvider = mServiceMap.get(i);
+ if (serviceProvider != null) {
+ serviceProvider.onDestroy();
+ }
+ }
+ mServiceMap.clear();
+ break;
case DATA_SERVICE_REQUEST_SETUP_DATA_CALL:
- if (service == null) break;
+ if (serviceProvider == null) break;
SetupDataCallRequest setupDataCallRequest = (SetupDataCallRequest) message.obj;
- service.setupDataCall(setupDataCallRequest.accessNetworkType,
+ serviceProvider.setupDataCall(setupDataCallRequest.accessNetworkType,
setupDataCallRequest.dataProfile, setupDataCallRequest.isRoaming,
setupDataCallRequest.allowRoaming, setupDataCallRequest.reason,
setupDataCallRequest.linkProperties,
@@ -345,46 +358,46 @@ public abstract class DataService extends Service {
break;
case DATA_SERVICE_REQUEST_DEACTIVATE_DATA_CALL:
- if (service == null) break;
+ if (serviceProvider == null) break;
DeactivateDataCallRequest deactivateDataCallRequest =
(DeactivateDataCallRequest) message.obj;
- service.deactivateDataCall(deactivateDataCallRequest.cid,
+ serviceProvider.deactivateDataCall(deactivateDataCallRequest.cid,
deactivateDataCallRequest.reason,
new DataServiceCallback(deactivateDataCallRequest.callback));
break;
case DATA_SERVICE_REQUEST_SET_INITIAL_ATTACH_APN:
- if (service == null) break;
+ if (serviceProvider == null) break;
SetInitialAttachApnRequest setInitialAttachApnRequest =
(SetInitialAttachApnRequest) message.obj;
- service.setInitialAttachApn(setInitialAttachApnRequest.dataProfile,
+ serviceProvider.setInitialAttachApn(setInitialAttachApnRequest.dataProfile,
setInitialAttachApnRequest.isRoaming,
new DataServiceCallback(setInitialAttachApnRequest.callback));
break;
case DATA_SERVICE_REQUEST_SET_DATA_PROFILE:
- if (service == null) break;
+ if (serviceProvider == null) break;
SetDataProfileRequest setDataProfileRequest =
(SetDataProfileRequest) message.obj;
- service.setDataProfile(setDataProfileRequest.dps,
+ serviceProvider.setDataProfile(setDataProfileRequest.dps,
setDataProfileRequest.isRoaming,
new DataServiceCallback(setDataProfileRequest.callback));
break;
case DATA_SERVICE_REQUEST_GET_DATA_CALL_LIST:
- if (service == null) break;
+ if (serviceProvider == null) break;
- service.getDataCallList(new DataServiceCallback(
+ serviceProvider.getDataCallList(new DataServiceCallback(
(IDataServiceCallback) message.obj));
break;
case DATA_SERVICE_REQUEST_REGISTER_DATA_CALL_LIST_CHANGED:
- if (service == null) break;
- service.registerForDataCallListChanged((IDataServiceCallback) message.obj);
+ if (serviceProvider == null) break;
+ serviceProvider.registerForDataCallListChanged((IDataServiceCallback) message.obj);
break;
case DATA_SERVICE_REQUEST_UNREGISTER_DATA_CALL_LIST_CHANGED:
- if (service == null) break;
+ if (serviceProvider == null) break;
callback = (IDataServiceCallback) message.obj;
- service.unregisterForDataCallListChanged(callback);
+ serviceProvider.unregisterForDataCallListChanged(callback);
break;
case DATA_SERVICE_INDICATION_DATA_CALL_LIST_CHANGED:
- if (service == null) break;
+ if (serviceProvider == null) break;
DataCallListChangedIndication indication =
(DataCallListChangedIndication) message.obj;
try {
@@ -423,67 +436,19 @@ public abstract class DataService extends Service {
loge("Unexpected intent " + intent);
return null;
}
-
- int slotId = intent.getIntExtra(
- DATA_SERVICE_EXTRA_SLOT_ID, SubscriptionManager.INVALID_SIM_SLOT_INDEX);
-
- if (!SubscriptionManager.isValidSlotIndex(slotId)) {
- loge("Invalid slot id " + slotId);
- return null;
- }
-
- log("onBind: slot id=" + slotId);
-
- IDataServiceWrapper binder = mBinderMap.get(slotId);
- if (binder == null) {
- Message msg = mHandler.obtainMessage(DATA_SERVICE_INTERNAL_REQUEST_INITIALIZE_SERVICE);
- msg.arg1 = slotId;
- msg.sendToTarget();
-
- binder = new IDataServiceWrapper(slotId);
- mBinderMap.put(slotId, binder);
- }
-
- return binder;
+ return mBinder;
}
/** @hide */
@Override
public boolean onUnbind(Intent intent) {
- int slotId = intent.getIntExtra(DATA_SERVICE_EXTRA_SLOT_ID,
- SubscriptionManager.INVALID_SIM_SLOT_INDEX);
- if (mBinderMap.get(slotId) != null) {
- DataServiceProvider serviceImpl;
- synchronized (mServiceMap) {
- serviceImpl = mServiceMap.get(slotId);
- }
- if (serviceImpl != null) {
- serviceImpl.onDestroy();
- }
- mBinderMap.remove(slotId);
- }
-
- // If all clients unbinds, quit the handler thread
- if (mBinderMap.size() == 0) {
- mHandlerThread.quit();
- }
-
+ mHandler.obtainMessage(DATA_SERVICE_REMOVE_ALL_DATA_SERVICE_PROVIDERS).sendToTarget();
return false;
}
/** @hide */
@Override
public void onDestroy() {
- synchronized (mServiceMap) {
- for (int i = 0; i < mServiceMap.size(); i++) {
- DataServiceProvider serviceImpl = mServiceMap.get(i);
- if (serviceImpl != null) {
- serviceImpl.onDestroy();
- }
- }
- mServiceMap.clear();
- }
-
mHandlerThread.quit();
}
@@ -491,68 +456,74 @@ public abstract class DataService extends Service {
* A wrapper around IDataService that forwards calls to implementations of {@link DataService}.
*/
private class IDataServiceWrapper extends IDataService.Stub {
+ @Override
+ public void createDataServiceProvider(int slotId) {
+ mHandler.obtainMessage(DATA_SERVICE_CREATE_DATA_SERVICE_PROVIDER, slotId, 0)
+ .sendToTarget();
+ }
- private final int mSlotId;
-
- IDataServiceWrapper(int slotId) {
- mSlotId = slotId;
+ @Override
+ public void removeDataServiceProvider(int slotId) {
+ mHandler.obtainMessage(DATA_SERVICE_REMOVE_DATA_SERVICE_PROVIDER, slotId, 0)
+ .sendToTarget();
}
@Override
- public void setupDataCall(int accessNetworkType, DataProfile dataProfile,
+ public void setupDataCall(int slotId, int accessNetworkType, DataProfile dataProfile,
boolean isRoaming, boolean allowRoaming, int reason,
LinkProperties linkProperties, IDataServiceCallback callback) {
- mHandler.obtainMessage(DATA_SERVICE_REQUEST_SETUP_DATA_CALL, mSlotId, 0,
+ mHandler.obtainMessage(DATA_SERVICE_REQUEST_SETUP_DATA_CALL, slotId, 0,
new SetupDataCallRequest(accessNetworkType, dataProfile, isRoaming,
allowRoaming, reason, linkProperties, callback))
.sendToTarget();
}
@Override
- public void deactivateDataCall(int cid, int reason, IDataServiceCallback callback) {
- mHandler.obtainMessage(DATA_SERVICE_REQUEST_DEACTIVATE_DATA_CALL, mSlotId, 0,
+ public void deactivateDataCall(int slotId, int cid, int reason,
+ IDataServiceCallback callback) {
+ mHandler.obtainMessage(DATA_SERVICE_REQUEST_DEACTIVATE_DATA_CALL, slotId, 0,
new DeactivateDataCallRequest(cid, reason, callback))
.sendToTarget();
}
@Override
- public void setInitialAttachApn(DataProfile dataProfile, boolean isRoaming,
+ public void setInitialAttachApn(int slotId, DataProfile dataProfile, boolean isRoaming,
IDataServiceCallback callback) {
- mHandler.obtainMessage(DATA_SERVICE_REQUEST_SET_INITIAL_ATTACH_APN, mSlotId, 0,
+ mHandler.obtainMessage(DATA_SERVICE_REQUEST_SET_INITIAL_ATTACH_APN, slotId, 0,
new SetInitialAttachApnRequest(dataProfile, isRoaming, callback))
.sendToTarget();
}
@Override
- public void setDataProfile(List<DataProfile> dps, boolean isRoaming,
+ public void setDataProfile(int slotId, List<DataProfile> dps, boolean isRoaming,
IDataServiceCallback callback) {
- mHandler.obtainMessage(DATA_SERVICE_REQUEST_SET_DATA_PROFILE, mSlotId, 0,
+ mHandler.obtainMessage(DATA_SERVICE_REQUEST_SET_DATA_PROFILE, slotId, 0,
new SetDataProfileRequest(dps, isRoaming, callback)).sendToTarget();
}
@Override
- public void getDataCallList(IDataServiceCallback callback) {
- mHandler.obtainMessage(DATA_SERVICE_REQUEST_GET_DATA_CALL_LIST, mSlotId, 0,
+ public void getDataCallList(int slotId, IDataServiceCallback callback) {
+ mHandler.obtainMessage(DATA_SERVICE_REQUEST_GET_DATA_CALL_LIST, slotId, 0,
callback).sendToTarget();
}
@Override
- public void registerForDataCallListChanged(IDataServiceCallback callback) {
+ public void registerForDataCallListChanged(int slotId, IDataServiceCallback callback) {
if (callback == null) {
loge("Callback is null");
return;
}
- mHandler.obtainMessage(DATA_SERVICE_REQUEST_REGISTER_DATA_CALL_LIST_CHANGED, mSlotId,
+ mHandler.obtainMessage(DATA_SERVICE_REQUEST_REGISTER_DATA_CALL_LIST_CHANGED, slotId,
0, callback).sendToTarget();
}
@Override
- public void unregisterForDataCallListChanged(IDataServiceCallback callback) {
+ public void unregisterForDataCallListChanged(int slotId, IDataServiceCallback callback) {
if (callback == null) {
loge("Callback is null");
return;
}
- mHandler.obtainMessage(DATA_SERVICE_REQUEST_UNREGISTER_DATA_CALL_LIST_CHANGED, mSlotId,
+ mHandler.obtainMessage(DATA_SERVICE_REQUEST_UNREGISTER_DATA_CALL_LIST_CHANGED, slotId,
0, callback).sendToTarget();
}
}
diff --git a/telephony/java/android/telephony/data/DataServiceCallback.java b/telephony/java/android/telephony/data/DataServiceCallback.java
index b6a81f94028b..08f33d948061 100644
--- a/telephony/java/android/telephony/data/DataServiceCallback.java
+++ b/telephony/java/android/telephony/data/DataServiceCallback.java
@@ -18,6 +18,7 @@ package android.telephony.data;
import android.annotation.IntDef;
import android.annotation.SystemApi;
+import android.net.LinkProperties;
import android.os.RemoteException;
import android.telephony.Rlog;
import android.telephony.data.DataService.DataServiceProvider;
@@ -46,7 +47,7 @@ public class DataServiceCallback {
@Retention(RetentionPolicy.SOURCE)
@IntDef({RESULT_SUCCESS, RESULT_ERROR_UNSUPPORTED, RESULT_ERROR_INVALID_ARG, RESULT_ERROR_BUSY,
RESULT_ERROR_ILLEGAL_STATE})
- public @interface Result {}
+ public @interface ResultCode {}
/** Request is completed successfully */
public static final int RESULT_SUCCESS = 0;
@@ -68,12 +69,12 @@ public class DataServiceCallback {
/**
* Called to indicate result for the request {@link DataServiceProvider#setupDataCall(int,
- * DataProfile, boolean, boolean, boolean, DataServiceCallback)}.
+ * DataProfile, boolean, boolean, int, LinkProperties, DataServiceCallback)} .
*
- * @param result The result code. Must be one of the {@link Result}.
+ * @param result The result code. Must be one of the {@link ResultCode}.
* @param response Setup data call response.
*/
- public void onSetupDataCallComplete(@Result int result, DataCallResponse response) {
+ public void onSetupDataCallComplete(@ResultCode int result, DataCallResponse response) {
IDataServiceCallback callback = mCallback.get();
if (callback != null) {
try {
@@ -86,11 +87,11 @@ public class DataServiceCallback {
/**
* Called to indicate result for the request {@link DataServiceProvider#deactivateDataCall(int,
- * boolean, boolean, DataServiceCallback)}.
+ * int, DataServiceCallback)}
*
- * @param result The result code. Must be one of the {@link Result}.
+ * @param result The result code. Must be one of the {@link ResultCode}.
*/
- public void onDeactivateDataCallComplete(@Result int result) {
+ public void onDeactivateDataCallComplete(@ResultCode int result) {
IDataServiceCallback callback = mCallback.get();
if (callback != null) {
try {
@@ -105,9 +106,9 @@ public class DataServiceCallback {
* Called to indicate result for the request {@link DataServiceProvider#setInitialAttachApn(
* DataProfile, boolean, DataServiceCallback)}.
*
- * @param result The result code. Must be one of the {@link Result}.
+ * @param result The result code. Must be one of the {@link ResultCode}.
*/
- public void onSetInitialAttachApnComplete(@Result int result) {
+ public void onSetInitialAttachApnComplete(@ResultCode int result) {
IDataServiceCallback callback = mCallback.get();
if (callback != null) {
try {
@@ -122,10 +123,10 @@ public class DataServiceCallback {
* Called to indicate result for the request {@link DataServiceProvider#setDataProfile(List,
* boolean, DataServiceCallback)}.
*
- * @param result The result code. Must be one of the {@link Result}.
+ * @param result The result code. Must be one of the {@link ResultCode}.
*/
@SystemApi
- public void onSetDataProfileComplete(@Result int result) {
+ public void onSetDataProfileComplete(@ResultCode int result) {
IDataServiceCallback callback = mCallback.get();
if (callback != null) {
try {
@@ -140,10 +141,11 @@ public class DataServiceCallback {
* Called to indicate result for the request {@link DataServiceProvider#getDataCallList(
* DataServiceCallback)}.
*
- * @param result The result code. Must be one of the {@link Result}.
+ * @param result The result code. Must be one of the {@link ResultCode}.
* @param dataCallList List of the current active data connection.
*/
- public void onGetDataCallListComplete(@Result int result, List<DataCallResponse> dataCallList) {
+ public void onGetDataCallListComplete(@ResultCode int result,
+ List<DataCallResponse> dataCallList) {
IDataServiceCallback callback = mCallback.get();
if (callback != null) {
try {
diff --git a/telephony/java/android/telephony/data/IDataService.aidl b/telephony/java/android/telephony/data/IDataService.aidl
index 07720b69e45f..d4d9be85ffa8 100644
--- a/telephony/java/android/telephony/data/IDataService.aidl
+++ b/telephony/java/android/telephony/data/IDataService.aidl
@@ -25,14 +25,17 @@ import android.telephony.data.IDataServiceCallback;
*/
oneway interface IDataService
{
- void setupDataCall(int accessNetwork, in DataProfile dataProfile, boolean isRoaming,
+ void createDataServiceProvider(int slotId);
+ void removeDataServiceProvider(int slotId);
+ void setupDataCall(int slotId, int accessNetwork, in DataProfile dataProfile, boolean isRoaming,
boolean allowRoaming, int reason, in LinkProperties linkProperties,
IDataServiceCallback callback);
- void deactivateDataCall(int cid, int reason, IDataServiceCallback callback);
- void setInitialAttachApn(in DataProfile dataProfile, boolean isRoaming,
+ void deactivateDataCall(int slotId, int cid, int reason, IDataServiceCallback callback);
+ void setInitialAttachApn(int slotId, in DataProfile dataProfile, boolean isRoaming,
IDataServiceCallback callback);
- void setDataProfile(in List<DataProfile> dps, boolean isRoaming, IDataServiceCallback callback);
- void getDataCallList(IDataServiceCallback callback);
- void registerForDataCallListChanged(IDataServiceCallback callback);
- void unregisterForDataCallListChanged(IDataServiceCallback callback);
+ void setDataProfile(int slotId, in List<DataProfile> dps, boolean isRoaming,
+ IDataServiceCallback callback);
+ void getDataCallList(int slotId, IDataServiceCallback callback);
+ void registerForDataCallListChanged(int slotId, IDataServiceCallback callback);
+ void unregisterForDataCallListChanged(int slotId, IDataServiceCallback callback);
}
diff --git a/test-mock/Android.mk b/test-mock/Android.mk
index 7926a77ccb01..5c586c7101a1 100644
--- a/test-mock/Android.mk
+++ b/test-mock/Android.mk
@@ -31,7 +31,7 @@ ifeq (,$(TARGET_BUILD_APPS)$(filter true,$(TARGET_BUILD_PDK)))
include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(android_test_mock_source_files)
-LOCAL_JAVA_LIBRARIES := core-oj core-libart framework
+LOCAL_JAVA_LIBRARIES := core-oj core-libart framework conscrypt okhttp bouncycastle
LOCAL_MODULE_CLASS := JAVA_LIBRARIES
LOCAL_DROIDDOC_SOURCE_PATH := $(LOCAL_PATH)/src/android/test/mock
@@ -116,7 +116,7 @@ update-android-test-mock-api: $(ANDROID_TEST_MOCK_OUTPUT_API_FILE) | $(ACP)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(android_test_mock_source_files)
-LOCAL_JAVA_LIBRARIES := core-oj core-libart framework
+LOCAL_JAVA_LIBRARIES := core-oj core-libart framework conscrypt okhttp bouncycastle
LOCAL_MODULE_CLASS := JAVA_LIBRARIES
LOCAL_DROIDDOC_SOURCE_PATH := $(LOCAL_PATH)/src/android/test/mock
diff --git a/wifi/tests/src/android/net/wifi/ParcelUtilTest.java b/wifi/tests/src/android/net/wifi/ParcelUtilTest.java
index 6787594b829c..0c3bf3b9ef2e 100644
--- a/wifi/tests/src/android/net/wifi/ParcelUtilTest.java
+++ b/wifi/tests/src/android/net/wifi/ParcelUtilTest.java
@@ -22,7 +22,7 @@ import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import android.os.Parcel;
-import android.test.suitebuilder.annotation.SmallTest;
+import android.support.test.filters.SmallTest;
import org.junit.Before;
import org.junit.Test;
diff --git a/wifi/tests/src/android/net/wifi/ScanResultTest.java b/wifi/tests/src/android/net/wifi/ScanResultTest.java
index 689ebbafe527..458c43dcd692 100644
--- a/wifi/tests/src/android/net/wifi/ScanResultTest.java
+++ b/wifi/tests/src/android/net/wifi/ScanResultTest.java
@@ -22,7 +22,7 @@ import static org.junit.Assert.assertNull;
import static org.mockito.Mockito.validateMockitoUsage;
import android.os.Parcel;
-import android.test.suitebuilder.annotation.SmallTest;
+import android.support.test.filters.SmallTest;
import android.net.wifi.WifiScanner.ScanSettings;
import org.junit.After;
diff --git a/wifi/tests/src/android/net/wifi/WifiEnterpriseConfigTest.java b/wifi/tests/src/android/net/wifi/WifiEnterpriseConfigTest.java
index 1a7dd132389e..e569efef5d91 100644
--- a/wifi/tests/src/android/net/wifi/WifiEnterpriseConfigTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiEnterpriseConfigTest.java
@@ -28,7 +28,7 @@ import android.net.wifi.WifiEnterpriseConfig.Eap;
import android.net.wifi.WifiEnterpriseConfig.Phase2;
import android.os.Parcel;
import android.security.Credentials;
-import android.test.suitebuilder.annotation.SmallTest;
+import android.support.test.filters.SmallTest;
import org.junit.Before;
import org.junit.Test;
diff --git a/wifi/tests/src/android/net/wifi/WifiManagerTest.java b/wifi/tests/src/android/net/wifi/WifiManagerTest.java
index 4b5f6452d392..7259695446a1 100644
--- a/wifi/tests/src/android/net/wifi/WifiManagerTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiManagerTest.java
@@ -51,7 +51,7 @@ import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.test.TestLooper;
-import android.test.suitebuilder.annotation.SmallTest;
+import android.support.test.filters.SmallTest;
import org.junit.Before;
import org.junit.Test;
diff --git a/wifi/tests/src/android/net/wifi/WifiScannerTest.java b/wifi/tests/src/android/net/wifi/WifiScannerTest.java
index a4366d454a67..96d5a5167480 100644
--- a/wifi/tests/src/android/net/wifi/WifiScannerTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiScannerTest.java
@@ -25,7 +25,7 @@ import android.content.Context;
import android.os.Handler;
import android.os.Parcel;
import android.os.test.TestLooper;
-import android.test.suitebuilder.annotation.SmallTest;
+import android.support.test.filters.SmallTest;
import android.net.wifi.WifiScanner.ScanSettings;
import com.android.internal.util.test.BidirectionalAsyncChannelServer;
diff --git a/wifi/tests/src/android/net/wifi/aware/TlvBufferUtilsTest.java b/wifi/tests/src/android/net/wifi/aware/TlvBufferUtilsTest.java
index 15641abd11f9..6ecd93114dc2 100644
--- a/wifi/tests/src/android/net/wifi/aware/TlvBufferUtilsTest.java
+++ b/wifi/tests/src/android/net/wifi/aware/TlvBufferUtilsTest.java
@@ -18,7 +18,7 @@ package android.net.wifi.aware;
import static org.hamcrest.core.IsEqual.equalTo;
-import android.test.suitebuilder.annotation.SmallTest;
+import android.support.test.filters.SmallTest;
import org.junit.Rule;
import org.junit.Test;
diff --git a/wifi/tests/src/android/net/wifi/aware/WifiAwareAgentNetworkSpecifierTest.java b/wifi/tests/src/android/net/wifi/aware/WifiAwareAgentNetworkSpecifierTest.java
index 2dd0537a7aff..0515e0637e03 100644
--- a/wifi/tests/src/android/net/wifi/aware/WifiAwareAgentNetworkSpecifierTest.java
+++ b/wifi/tests/src/android/net/wifi/aware/WifiAwareAgentNetworkSpecifierTest.java
@@ -20,7 +20,7 @@ import static org.hamcrest.core.IsEqual.equalTo;
import static org.junit.Assert.assertEquals;
import android.os.Parcel;
-import android.test.suitebuilder.annotation.SmallTest;
+import android.support.test.filters.SmallTest;
import org.junit.Rule;
import org.junit.Test;
diff --git a/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java b/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java
index 9cab66a240a7..b0a048d77730 100644
--- a/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java
+++ b/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java
@@ -31,7 +31,7 @@ import android.os.Handler;
import android.os.IBinder;
import android.os.Parcel;
import android.os.test.TestLooper;
-import android.test.suitebuilder.annotation.SmallTest;
+import android.support.test.filters.SmallTest;
import libcore.util.HexEncoding;
diff --git a/wifi/tests/src/android/net/wifi/hotspot2/ConfigParserTest.java b/wifi/tests/src/android/net/wifi/hotspot2/ConfigParserTest.java
index 56bb4375acdd..f32fe599cd95 100644
--- a/wifi/tests/src/android/net/wifi/hotspot2/ConfigParserTest.java
+++ b/wifi/tests/src/android/net/wifi/hotspot2/ConfigParserTest.java
@@ -22,7 +22,7 @@ import static org.junit.Assert.assertTrue;
import android.net.wifi.FakeKeys;
import android.net.wifi.hotspot2.pps.Credential;
import android.net.wifi.hotspot2.pps.HomeSp;
-import android.test.suitebuilder.annotation.SmallTest;
+import android.support.test.filters.SmallTest;
import java.io.BufferedReader;
import java.io.IOException;
diff --git a/wifi/tests/src/android/net/wifi/hotspot2/OsuProviderTest.java b/wifi/tests/src/android/net/wifi/hotspot2/OsuProviderTest.java
index 9670bfab89f8..d3f91f06da61 100644
--- a/wifi/tests/src/android/net/wifi/hotspot2/OsuProviderTest.java
+++ b/wifi/tests/src/android/net/wifi/hotspot2/OsuProviderTest.java
@@ -23,7 +23,7 @@ import android.graphics.drawable.Icon;
import android.net.Uri;
import android.net.wifi.WifiSsid;
import android.os.Parcel;
-import android.test.suitebuilder.annotation.SmallTest;
+import android.support.test.filters.SmallTest;
import org.junit.Test;
diff --git a/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java b/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java
index afcf3e344c27..940adc809535 100644
--- a/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java
+++ b/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java
@@ -25,7 +25,7 @@ import android.net.wifi.hotspot2.pps.HomeSp;
import android.net.wifi.hotspot2.pps.Policy;
import android.net.wifi.hotspot2.pps.UpdateParameter;
import android.os.Parcel;
-import android.test.suitebuilder.annotation.SmallTest;
+import android.support.test.filters.SmallTest;
import android.util.Base64;
import org.junit.Test;
diff --git a/wifi/tests/src/android/net/wifi/hotspot2/omadm/PpsMoParserTest.java b/wifi/tests/src/android/net/wifi/hotspot2/omadm/PpsMoParserTest.java
index afa9fd6a9e8b..707b64f780c5 100644
--- a/wifi/tests/src/android/net/wifi/hotspot2/omadm/PpsMoParserTest.java
+++ b/wifi/tests/src/android/net/wifi/hotspot2/omadm/PpsMoParserTest.java
@@ -25,7 +25,7 @@ import android.net.wifi.hotspot2.pps.Credential;
import android.net.wifi.hotspot2.pps.HomeSp;
import android.net.wifi.hotspot2.pps.Policy;
import android.net.wifi.hotspot2.pps.UpdateParameter;
-import android.test.suitebuilder.annotation.SmallTest;
+import android.support.test.filters.SmallTest;
import android.text.TextUtils;
import org.junit.Test;
diff --git a/wifi/tests/src/android/net/wifi/hotspot2/omadm/XMLParserTest.java b/wifi/tests/src/android/net/wifi/hotspot2/omadm/XMLParserTest.java
index c2dcec693b83..ef478c7a105c 100644
--- a/wifi/tests/src/android/net/wifi/hotspot2/omadm/XMLParserTest.java
+++ b/wifi/tests/src/android/net/wifi/hotspot2/omadm/XMLParserTest.java
@@ -20,7 +20,7 @@ import static org.junit.Assert.assertTrue;
import android.net.wifi.hotspot2.omadm.XMLNode;
import android.net.wifi.hotspot2.omadm.XMLParser;
-import android.test.suitebuilder.annotation.SmallTest;
+import android.support.test.filters.SmallTest;
import org.junit.Before;
import org.junit.Test;
diff --git a/wifi/tests/src/android/net/wifi/hotspot2/pps/CredentialTest.java b/wifi/tests/src/android/net/wifi/hotspot2/pps/CredentialTest.java
index 9bfc0105fcc9..b573adf60863 100644
--- a/wifi/tests/src/android/net/wifi/hotspot2/pps/CredentialTest.java
+++ b/wifi/tests/src/android/net/wifi/hotspot2/pps/CredentialTest.java
@@ -22,7 +22,7 @@ import static org.junit.Assert.assertTrue;
import android.net.wifi.EAPConstants;
import android.net.wifi.FakeKeys;
import android.os.Parcel;
-import android.test.suitebuilder.annotation.SmallTest;
+import android.support.test.filters.SmallTest;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
diff --git a/wifi/tests/src/android/net/wifi/hotspot2/pps/HomeSpTest.java b/wifi/tests/src/android/net/wifi/hotspot2/pps/HomeSpTest.java
index c41c11f16acf..5c9df6a0186c 100644
--- a/wifi/tests/src/android/net/wifi/hotspot2/pps/HomeSpTest.java
+++ b/wifi/tests/src/android/net/wifi/hotspot2/pps/HomeSpTest.java
@@ -20,7 +20,7 @@ import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import android.os.Parcel;
-import android.test.suitebuilder.annotation.SmallTest;
+import android.support.test.filters.SmallTest;
import org.junit.Test;
diff --git a/wifi/tests/src/android/net/wifi/hotspot2/pps/PolicyTest.java b/wifi/tests/src/android/net/wifi/hotspot2/pps/PolicyTest.java
index 2a3676463936..171d6ff0781f 100644
--- a/wifi/tests/src/android/net/wifi/hotspot2/pps/PolicyTest.java
+++ b/wifi/tests/src/android/net/wifi/hotspot2/pps/PolicyTest.java
@@ -20,7 +20,7 @@ import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import android.os.Parcel;
-import android.test.suitebuilder.annotation.SmallTest;
+import android.support.test.filters.SmallTest;
import android.util.Base64;
import org.junit.Test;
diff --git a/wifi/tests/src/android/net/wifi/hotspot2/pps/UpdateParameterTest.java b/wifi/tests/src/android/net/wifi/hotspot2/pps/UpdateParameterTest.java
index 551ed43c5efa..2a7526bc3de6 100644
--- a/wifi/tests/src/android/net/wifi/hotspot2/pps/UpdateParameterTest.java
+++ b/wifi/tests/src/android/net/wifi/hotspot2/pps/UpdateParameterTest.java
@@ -20,7 +20,7 @@ import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import android.os.Parcel;
-import android.test.suitebuilder.annotation.SmallTest;
+import android.support.test.filters.SmallTest;
import android.util.Base64;
import org.junit.Test;