summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Android.bp1
-rw-r--r--api/removed.txt4
-rw-r--r--cmds/statsd/src/main.cpp2
-rw-r--r--core/java/android/app/ApplicationPackageManager.java10
-rw-r--r--core/java/android/app/KeyguardManager.java8
-rw-r--r--core/java/android/provider/DeviceConfig.java3
-rw-r--r--core/java/android/provider/TEST_MAPPING8
-rw-r--r--packages/SettingsProvider/test/src/com/android/providers/settings/BaseSettingsProviderTest.java16
-rw-r--r--packages/SettingsProvider/test/src/com/android/providers/settings/InstallNonMarketAppsDeprecationTest.java4
-rw-r--r--packages/SettingsProvider/test/src/com/android/providers/settings/SettingsBackupAgentTest.java2
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java54
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java28
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/brightline/BrightLineFalsingManager.java15
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/brightline/DiagonalClassifier.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/brightline/DistanceClassifier.java16
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/brightline/ProximityClassifier.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/brightline/ZigZagClassifier.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java26
-rw-r--r--packages/SystemUI/src/com/android/systemui/util/DeviceConfigProxy.java131
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java10
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingManagerProxyTest.java48
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/DiagonalClassifierTest.java4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/DistanceClassifierTest.java4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/ProximityClassifierTest.java5
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/ZigZagClassifierTest.java4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java8
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/util/DeviceConfigProxyFake.java151
-rw-r--r--services/Android.bp1
-rw-r--r--services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java248
-rw-r--r--services/accessibility/java/com/android/server/accessibility/gestures/TouchState.java94
-rw-r--r--services/appprediction/java/com/android/server/appprediction/AppPredictionManagerService.java20
-rw-r--r--services/appprediction/java/com/android/server/appprediction/AppPredictionPerUserService.java34
-rw-r--r--services/appprediction/java/com/android/server/appprediction/RemoteAppPredictionService.java7
-rw-r--r--services/core/java/com/android/server/compat/CompatConfig.java10
-rw-r--r--services/core/java/com/android/server/hdmi/HdmiControlService.java17
-rw-r--r--services/core/java/com/android/server/infra/AbstractMasterSystemService.java156
-rw-r--r--services/core/java/com/android/server/pm/BackgroundDexOptService.java139
-rw-r--r--services/core/java/com/android/server/pm/permission/PermissionManagerService.java10
-rw-r--r--services/tests/servicestests/src/com/android/server/accessibility/gestures/TouchExplorerTest.java49
-rw-r--r--tests/BackgroundDexOptServiceIntegrationTests/AndroidManifest.xml2
-rw-r--r--tests/BackgroundDexOptServiceIntegrationTests/src/com/android/server/pm/BackgroundDexOptServiceIntegrationTests.java177
42 files changed, 1223 insertions, 339 deletions
diff --git a/Android.bp b/Android.bp
index d136a5dba998..121decbbec50 100644
--- a/Android.bp
+++ b/Android.bp
@@ -390,7 +390,6 @@ java_library {
platform_compat_config {
name: "framework-platform-compat-config",
- prefix: "framework",
src: ":framework-annotation-proc",
}
diff --git a/api/removed.txt b/api/removed.txt
index db784a8d792c..74a934672adb 100644
--- a/api/removed.txt
+++ b/api/removed.txt
@@ -5,10 +5,6 @@ package android.app {
method @Deprecated public static int getMaxNumPictureInPictureActions();
}
- public class KeyguardManager {
- method @Deprecated public void dismissKeyguard(@NonNull android.app.Activity, @Nullable android.app.KeyguardManager.KeyguardDismissCallback, @Nullable android.os.Handler);
- }
-
public class Notification implements android.os.Parcelable {
method @Deprecated public String getChannel();
method public static Class<? extends android.app.Notification.Style> getNotificationStyleClass(String);
diff --git a/cmds/statsd/src/main.cpp b/cmds/statsd/src/main.cpp
index 68082c2dc4d2..42132ee0daae 100644
--- a/cmds/statsd/src/main.cpp
+++ b/cmds/statsd/src/main.cpp
@@ -78,7 +78,7 @@ int main(int /*argc*/, char** /*argv*/) {
ps->giveThreadPoolName();
IPCThreadState::self()->disableBackgroundScheduling(true);
- ::android::hardware::configureRpcThreadpool(1 /*threads*/, false /*willJoin*/);
+ ::android::hardware::configureRpcThreadpool(4 /*threads*/, false /*willJoin*/);
std::shared_ptr<LogEventQueue> eventQueue =
std::make_shared<LogEventQueue>(2000 /*buffer limit. Buffer is NOT pre-allocated*/);
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 0478ac89fbbb..d74399c54bda 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -127,6 +127,7 @@ public class ApplicationPackageManager extends PackageManager {
* @hide
*/
public static final boolean DEBUG_TRACE_GRANTS = false;
+ public static final boolean DEBUG_TRACE_PERMISSION_UPDATES = false;
private static final int DEFAULT_EPHEMERAL_COOKIE_MAX_SIZE_BYTES = 16384; // 16KB
@@ -690,7 +691,7 @@ public class ApplicationPackageManager extends PackageManager {
UserHandle user) {
if (DEBUG_TRACE_GRANTS
&& shouldTraceGrant(packageName, permissionName, user.getIdentifier())) {
- Log.i(TAG, "App " + mContext.getPackageName() + " is granting "
+ Log.i(TAG, "App " + mContext.getPackageName() + " is granting " + packageName + " "
+ permissionName + " for user " + user.getIdentifier(), new RuntimeException());
}
try {
@@ -708,9 +709,9 @@ public class ApplicationPackageManager extends PackageManager {
@Override
public void revokeRuntimePermission(String packageName, String permName, UserHandle user) {
- if (DEBUG_TRACE_GRANTS
+ if (DEBUG_TRACE_PERMISSION_UPDATES
&& shouldTraceGrant(packageName, permName, user.getIdentifier())) {
- Log.i(TAG, "App " + mContext.getPackageName() + " is revoking "
+ Log.i(TAG, "App " + mContext.getPackageName() + " is revoking " + packageName + " "
+ permName + " for user " + user.getIdentifier(), new RuntimeException());
}
try {
@@ -734,9 +735,10 @@ public class ApplicationPackageManager extends PackageManager {
@Override
public void updatePermissionFlags(String permName, String packageName,
int flagMask, int flagValues, UserHandle user) {
- if (DEBUG_TRACE_GRANTS
+ if (DEBUG_TRACE_PERMISSION_UPDATES
&& shouldTraceGrant(packageName, permName, user.getIdentifier())) {
Log.i(TAG, "App " + mContext.getPackageName() + " is updating flags for "
+ + packageName + " "
+ permName + " for user " + user.getIdentifier() + ": "
+ DebugUtils.flagsToString(PackageManager.class, "FLAG_PERMISSION_", flagMask)
+ " := " + DebugUtils.flagsToString(
diff --git a/core/java/android/app/KeyguardManager.java b/core/java/android/app/KeyguardManager.java
index 667758755c99..9b667a118ebc 100644
--- a/core/java/android/app/KeyguardManager.java
+++ b/core/java/android/app/KeyguardManager.java
@@ -32,7 +32,6 @@ import android.content.pm.ResolveInfo;
import android.hardware.biometrics.BiometricPrompt;
import android.os.Binder;
import android.os.Build;
-import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.ServiceManager;
@@ -508,13 +507,6 @@ public class KeyguardManager {
}
}
- /** @removed */
- @Deprecated
- public void dismissKeyguard(@NonNull Activity activity,
- @Nullable KeyguardDismissCallback callback, @Nullable Handler handler) {
- requestDismissKeyguard(activity, callback);
- }
-
/**
* If the device is currently locked (see {@link #isKeyguardLocked()}, requests the Keyguard to
* be dismissed.
diff --git a/core/java/android/provider/DeviceConfig.java b/core/java/android/provider/DeviceConfig.java
index b7676b611fe3..4b9daf1c9486 100644
--- a/core/java/android/provider/DeviceConfig.java
+++ b/core/java/android/provider/DeviceConfig.java
@@ -775,8 +775,9 @@ public final class DeviceConfig {
*
* @param namespace The namespace these properties belong to.
* @param keyValueMap A map between property names and property values.
+ * @hide
*/
- Properties(@NonNull String namespace, @Nullable Map<String, String> keyValueMap) {
+ public Properties(@NonNull String namespace, @Nullable Map<String, String> keyValueMap) {
Preconditions.checkNotNull(namespace);
mNamespace = namespace;
mMap = new HashMap();
diff --git a/core/java/android/provider/TEST_MAPPING b/core/java/android/provider/TEST_MAPPING
index 52a6a4585581..773be80be270 100644
--- a/core/java/android/provider/TEST_MAPPING
+++ b/core/java/android/provider/TEST_MAPPING
@@ -7,6 +7,14 @@
"include-annotation": "android.platform.test.annotations.Presubmit"
}
]
+ },
+ {
+ "name": "SettingsProviderTest",
+ "options": [
+ {
+ "include-annotation": "android.platform.test.annotations.Presubmit"
+ }
+ ]
}
]
}
diff --git a/packages/SettingsProvider/test/src/com/android/providers/settings/BaseSettingsProviderTest.java b/packages/SettingsProvider/test/src/com/android/providers/settings/BaseSettingsProviderTest.java
index 68efa6779f04..ce1da4a6ad7d 100644
--- a/packages/SettingsProvider/test/src/com/android/providers/settings/BaseSettingsProviderTest.java
+++ b/packages/SettingsProvider/test/src/com/android/providers/settings/BaseSettingsProviderTest.java
@@ -31,6 +31,8 @@ import androidx.test.runner.AndroidJUnit4;
import libcore.io.Streams;
+import org.junit.After;
+import org.junit.Before;
import org.junit.runner.RunWith;
import java.io.FileInputStream;
@@ -60,6 +62,20 @@ abstract class BaseSettingsProviderTest {
private int mSecondaryUserId = Integer.MIN_VALUE;
+ @Before
+ public void setUp() {
+ Settings.Global.clearProviderForTest();
+ Settings.Secure.clearProviderForTest();
+ Settings.System.clearProviderForTest();
+ }
+
+ @After
+ public void tearDown() {
+ Settings.Global.clearProviderForTest();
+ Settings.Secure.clearProviderForTest();
+ Settings.System.clearProviderForTest();
+ }
+
protected void setStringViaFrontEndApiSetting(int type, String name, String value, int userId) {
ContentResolver contentResolver = getContext().getContentResolver();
diff --git a/packages/SettingsProvider/test/src/com/android/providers/settings/InstallNonMarketAppsDeprecationTest.java b/packages/SettingsProvider/test/src/com/android/providers/settings/InstallNonMarketAppsDeprecationTest.java
index 863b0352913a..ff11f70b8ed1 100644
--- a/packages/SettingsProvider/test/src/com/android/providers/settings/InstallNonMarketAppsDeprecationTest.java
+++ b/packages/SettingsProvider/test/src/com/android/providers/settings/InstallNonMarketAppsDeprecationTest.java
@@ -84,8 +84,10 @@ public class InstallNonMarketAppsDeprecationTest extends BaseSettingsProviderTes
return line.trim();
}
+ @Override
@Before
public void setUp() {
+ super.setUp();
mUm = (UserManager) getContext().getSystemService(Context.USER_SERVICE);
mHasUserRestriction = mUm.hasUserRestriction(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES);
mSystemSetUserRestriction = mUm.getUserRestrictionSource(
@@ -145,8 +147,10 @@ public class InstallNonMarketAppsDeprecationTest extends BaseSettingsProviderTes
assertTrue("Invalid value", value.equals("1") || value.equals("0"));
}
+ @Override
@After
public void tearDown() {
+ super.tearDown();
if (!mHasUserRestriction || mSystemSetUserRestriction) {
// The test may have modified the user restriction state. Restore it.
mUm.setUserRestriction(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES,
diff --git a/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsBackupAgentTest.java b/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsBackupAgentTest.java
index cf8e1a5c2b14..12ca92f02e7a 100644
--- a/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsBackupAgentTest.java
+++ b/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsBackupAgentTest.java
@@ -64,8 +64,10 @@ public class SettingsBackupAgentTest extends BaseSettingsProviderTest {
private TestFriendlySettingsBackupAgent mAgentUnderTest;
private Context mContext;
+ @Override
@Before
public void setUp() {
+ super.setUp();
mContext = new ContextWithMockContentResolver(getContext());
mAgentUnderTest = new TestFriendlySettingsBackupAgent();
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 1714cd5163e7..aa1d8b4d5287 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -18,6 +18,8 @@ package com.android.keyguard;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+import static android.content.Intent.ACTION_USER_REMOVED;
+import static android.content.Intent.ACTION_USER_STOPPED;
import static android.content.Intent.ACTION_USER_UNLOCKED;
import static android.os.BatteryManager.BATTERY_HEALTH_UNKNOWN;
import static android.os.BatteryManager.BATTERY_STATUS_FULL;
@@ -162,6 +164,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
private static final int MSG_DEVICE_POLICY_MANAGER_STATE_CHANGED = 337;
private static final int MSG_TELEPHONY_CAPABLE = 338;
private static final int MSG_TIMEZONE_UPDATE = 339;
+ private static final int MSG_USER_STOPPED = 340;
+ private static final int MSG_USER_REMOVED = 341;
/** Biometric authentication state: Not listening. */
private static final int BIOMETRIC_STATE_STOPPED = 0;
@@ -375,7 +379,13 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
handleDreamingStateChanged(msg.arg1);
break;
case MSG_USER_UNLOCKED:
- handleUserUnlocked();
+ handleUserUnlocked(msg.arg1);
+ break;
+ case MSG_USER_STOPPED:
+ handleUserStopped(msg.arg1);
+ break;
+ case MSG_USER_REMOVED:
+ handleUserRemoved(msg.arg1);
break;
case MSG_ASSISTANT_STACK_CHANGED:
setAssistantVisible((boolean) msg.obj);
@@ -427,6 +437,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
}
};
+ private SparseBooleanArray mUserIsUnlocked = new SparseBooleanArray();
private SparseBooleanArray mUserHasTrust = new SparseBooleanArray();
private SparseBooleanArray mUserTrustIsManaged = new SparseBooleanArray();
private SparseBooleanArray mUserFingerprintAuthenticated = new SparseBooleanArray();
@@ -1207,7 +1218,14 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
.equals(action)) {
mHandler.sendEmptyMessage(MSG_DPM_STATE_CHANGED);
} else if (ACTION_USER_UNLOCKED.equals(action)) {
- mHandler.sendEmptyMessage(MSG_USER_UNLOCKED);
+ mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_UNLOCKED,
+ getSendingUserId(), 0));
+ } else if (ACTION_USER_STOPPED.equals(action)) {
+ mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_STOPPED,
+ intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1), 0));
+ } else if (ACTION_USER_REMOVED.equals(action)) {
+ mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_REMOVED,
+ intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1), 0));
}
}
};
@@ -1558,8 +1576,9 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
}
}
- private void handleUserUnlocked() {
+ private void handleUserUnlocked(int userId) {
checkIsHandlerThread();
+ mUserIsUnlocked.put(userId, true);
mNeedsSlowUnlockTransition = resolveNeedsSlowUnlockTransition();
for (int i = 0; i < mCallbacks.size(); i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
@@ -1569,6 +1588,16 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
}
}
+ private void handleUserStopped(int userId) {
+ checkIsHandlerThread();
+ mUserIsUnlocked.put(userId, mUserManager.isUserUnlocked(userId));
+ }
+
+ private void handleUserRemoved(int userId) {
+ checkIsHandlerThread();
+ mUserIsUnlocked.delete(userId);
+ }
+
@VisibleForTesting
protected KeyguardUpdateMonitor(Context context) {
mContext = context;
@@ -1612,6 +1641,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
allUserFilter.addAction(ACTION_FACE_UNLOCK_STOPPED);
allUserFilter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
allUserFilter.addAction(ACTION_USER_UNLOCKED);
+ allUserFilter.addAction(ACTION_USER_STOPPED);
+ allUserFilter.addAction(ACTION_USER_REMOVED);
context.registerReceiverAsUser(mBroadcastAllReceiver, UserHandle.ALL, allUserFilter,
null, mHandler);
@@ -1666,6 +1697,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
ActivityManagerWrapper.getInstance().registerTaskStackListener(mTaskStackListener);
mUserManager = context.getSystemService(UserManager.class);
mIsPrimaryUser = mUserManager.isPrimaryUser();
+ int user = ActivityManager.getCurrentUser();
+ mUserIsUnlocked.put(user, mUserManager.isUserUnlocked(user));
mDevicePolicyManager = context.getSystemService(DevicePolicyManager.class);
mLogoutEnabled = mDevicePolicyManager.isLogoutEnabled();
updateAirplaneModeState();
@@ -1709,6 +1742,19 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
}
/**
+ * If a user is encrypted or not.
+ * This is NOT related to the lock screen being visible or not.
+ *
+ * @param userId The user.
+ * @return {@code true} when encrypted.
+ * @see UserManager#isUserUnlocked()
+ * @see Intent#ACTION_USER_UNLOCKED
+ */
+ public boolean isUserUnlocked(int userId) {
+ return mUserIsUnlocked.get(userId);
+ }
+
+ /**
* Called whenever passive authentication is requested or aborted by a sensor.
*
* @param active If the interrupt started or ended.
@@ -2297,7 +2343,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
}
private boolean resolveNeedsSlowUnlockTransition() {
- if (mUserManager.isUserUnlocked(getCurrentUser())) {
+ if (isUserUnlocked(getCurrentUser())) {
return false;
}
Intent homeIntent = new Intent(Intent.ACTION_MAIN)
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java
index 41203348d7a0..efac147fc6b9 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java
@@ -35,6 +35,7 @@ import com.android.systemui.plugins.FalsingPlugin;
import com.android.systemui.plugins.PluginListener;
import com.android.systemui.shared.plugins.PluginManager;
import com.android.systemui.util.AsyncSensorManager;
+import com.android.systemui.util.DeviceConfigProxy;
import java.io.PrintWriter;
@@ -51,18 +52,23 @@ import javax.inject.Singleton;
public class FalsingManagerProxy implements FalsingManager {
private FalsingManager mInternalFalsingManager;
- private final Handler mMainHandler;
+ private DeviceConfig.OnPropertiesChangedListener mDeviceConfigListener;
+ private final DeviceConfigProxy mDeviceConfig;
private boolean mBrightlineEnabled;
@Inject
FalsingManagerProxy(Context context, PluginManager pluginManager,
- @Named(MAIN_HANDLER_NAME) Handler handler) {
- mMainHandler = handler;
+ @Named(MAIN_HANDLER_NAME) Handler handler, DeviceConfigProxy deviceConfig) {
+ mDeviceConfig = deviceConfig;
+ mDeviceConfigListener =
+ properties -> onDeviceConfigPropertiesChanged(context, properties.getNamespace());
setupFalsingManager(context);
- DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_SYSTEMUI,
- command -> mMainHandler.post(command),
- properties -> onDeviceConfigPropertiesChanged(context, properties.getNamespace())
+ mDeviceConfig.addOnPropertiesChangedListener(
+ DeviceConfig.NAMESPACE_SYSTEMUI,
+ handler::post,
+ mDeviceConfigListener
);
+
final PluginListener<FalsingPlugin> mPluginListener = new PluginListener<FalsingPlugin>() {
public void onPluginConnected(FalsingPlugin plugin, Context context) {
FalsingManager pluginFalsingManager = plugin.getFalsingManager(context);
@@ -91,9 +97,8 @@ public class FalsingManagerProxy implements FalsingManager {
/**
* Chooses the FalsingManager implementation.
*/
- @VisibleForTesting
- public void setupFalsingManager(Context context) {
- boolean brightlineEnabled = DeviceConfig.getBoolean(
+ private void setupFalsingManager(Context context) {
+ boolean brightlineEnabled = mDeviceConfig.getBoolean(
DeviceConfig.NAMESPACE_SYSTEMUI, BRIGHTLINE_FALSING_MANAGER_ENABLED, true);
if (brightlineEnabled == mBrightlineEnabled && mInternalFalsingManager != null) {
return;
@@ -109,10 +114,10 @@ public class FalsingManagerProxy implements FalsingManager {
mInternalFalsingManager = new BrightLineFalsingManager(
new FalsingDataProvider(context.getResources().getDisplayMetrics()),
Dependency.get(AsyncSensorManager.class),
- KeyguardUpdateMonitor.getInstance(context)
+ KeyguardUpdateMonitor.getInstance(context),
+ mDeviceConfig
);
}
-
}
/**
@@ -305,6 +310,7 @@ public class FalsingManagerProxy implements FalsingManager {
@Override
public void cleanup() {
+ mDeviceConfig.removeOnPropertiesChangedListener(mDeviceConfigListener);
mInternalFalsingManager.cleanup();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/brightline/BrightLineFalsingManager.java b/packages/SystemUI/src/com/android/systemui/classifier/brightline/BrightLineFalsingManager.java
index 9e0b7025ddf8..9e646b627bd2 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/brightline/BrightLineFalsingManager.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/brightline/BrightLineFalsingManager.java
@@ -33,6 +33,7 @@ import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardUpdateMonitorCallback;
import com.android.systemui.classifier.Classifier;
import com.android.systemui.plugins.FalsingManager;
+import com.android.systemui.util.DeviceConfigProxy;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -88,7 +89,8 @@ public class BrightLineFalsingManager implements FalsingManager {
public BrightLineFalsingManager(
FalsingDataProvider falsingDataProvider,
SensorManager sensorManager,
- KeyguardUpdateMonitor keyguardUpdateMonitor) {
+ KeyguardUpdateMonitor keyguardUpdateMonitor,
+ DeviceConfigProxy deviceConfigProxy) {
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
mDataProvider = falsingDataProvider;
mSensorManager = sensorManager;
@@ -96,15 +98,16 @@ public class BrightLineFalsingManager implements FalsingManager {
mMetricsLogger = new MetricsLogger();
mClassifiers = new ArrayList<>();
- DistanceClassifier distanceClassifier = new DistanceClassifier(mDataProvider);
- ProximityClassifier proximityClassifier = new ProximityClassifier(distanceClassifier,
- mDataProvider);
+ DistanceClassifier distanceClassifier =
+ new DistanceClassifier(mDataProvider, deviceConfigProxy);
+ ProximityClassifier proximityClassifier =
+ new ProximityClassifier(distanceClassifier, mDataProvider, deviceConfigProxy);
mClassifiers.add(new PointerCountClassifier(mDataProvider));
mClassifiers.add(new TypeClassifier(mDataProvider));
- mClassifiers.add(new DiagonalClassifier(mDataProvider));
+ mClassifiers.add(new DiagonalClassifier(mDataProvider, deviceConfigProxy));
mClassifiers.add(distanceClassifier);
mClassifiers.add(proximityClassifier);
- mClassifiers.add(new ZigZagClassifier(mDataProvider));
+ mClassifiers.add(new ZigZagClassifier(mDataProvider, deviceConfigProxy));
}
private void registerSensors() {
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/brightline/DiagonalClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/brightline/DiagonalClassifier.java
index cc6645415fd8..9c03b915000e 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/brightline/DiagonalClassifier.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/brightline/DiagonalClassifier.java
@@ -23,6 +23,8 @@ import static com.android.systemui.classifier.Classifier.RIGHT_AFFORDANCE;
import android.provider.DeviceConfig;
+import com.android.systemui.util.DeviceConfigProxy;
+
/**
* False on swipes that are too close to 45 degrees.
*
@@ -42,14 +44,14 @@ class DiagonalClassifier extends FalsingClassifier {
private final float mHorizontalAngleRange;
private final float mVerticalAngleRange;
- DiagonalClassifier(FalsingDataProvider dataProvider) {
+ DiagonalClassifier(FalsingDataProvider dataProvider, DeviceConfigProxy deviceConfigProxy) {
super(dataProvider);
- mHorizontalAngleRange = DeviceConfig.getFloat(
+ mHorizontalAngleRange = deviceConfigProxy.getFloat(
DeviceConfig.NAMESPACE_SYSTEMUI,
BRIGHTLINE_FALSING_DIAGONAL_HORIZONTAL_ANGLE_RANGE,
HORIZONTAL_ANGLE_RANGE);
- mVerticalAngleRange = DeviceConfig.getFloat(
+ mVerticalAngleRange = deviceConfigProxy.getFloat(
DeviceConfig.NAMESPACE_SYSTEMUI,
BRIGHTLINE_FALSING_DIAGONAL_VERTICAL_ANGLE_RANGE,
VERTICAL_ANGLE_RANGE);
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/brightline/DistanceClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/brightline/DistanceClassifier.java
index a6a617dc51de..0954f9e6e672 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/brightline/DistanceClassifier.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/brightline/DistanceClassifier.java
@@ -27,6 +27,8 @@ import android.provider.DeviceConfig;
import android.view.MotionEvent;
import android.view.VelocityTracker;
+import com.android.systemui.util.DeviceConfigProxy;
+
import java.util.List;
/**
@@ -50,35 +52,35 @@ class DistanceClassifier extends FalsingClassifier {
private boolean mDistanceDirty;
private DistanceVectors mCachedDistance;
- DistanceClassifier(FalsingDataProvider dataProvider) {
+ DistanceClassifier(FalsingDataProvider dataProvider, DeviceConfigProxy deviceConfigProxy) {
super(dataProvider);
- mVelocityToDistanceMultiplier = DeviceConfig.getFloat(
+ mVelocityToDistanceMultiplier = deviceConfigProxy.getFloat(
DeviceConfig.NAMESPACE_SYSTEMUI,
BRIGHTLINE_FALSING_DISTANCE_VELOCITY_TO_DISTANCE,
VELOCITY_TO_DISTANCE);
- float horizontalFlingThresholdIn = DeviceConfig.getFloat(
+ float horizontalFlingThresholdIn = deviceConfigProxy.getFloat(
DeviceConfig.NAMESPACE_SYSTEMUI,
BRIGHTLINE_FALSING_DISTANCE_HORIZONTAL_FLING_THRESHOLD_IN,
HORIZONTAL_FLING_THRESHOLD_DISTANCE_IN);
- float verticalFlingThresholdIn = DeviceConfig.getFloat(
+ float verticalFlingThresholdIn = deviceConfigProxy.getFloat(
DeviceConfig.NAMESPACE_SYSTEMUI,
BRIGHTLINE_FALSING_DISTANCE_VERTICAL_FLING_THRESHOLD_IN,
VERTICAL_FLING_THRESHOLD_DISTANCE_IN);
- float horizontalSwipeThresholdIn = DeviceConfig.getFloat(
+ float horizontalSwipeThresholdIn = deviceConfigProxy.getFloat(
DeviceConfig.NAMESPACE_SYSTEMUI,
BRIGHTLINE_FALSING_DISTANCE_HORIZONTAL_SWIPE_THRESHOLD_IN,
HORIZONTAL_SWIPE_THRESHOLD_DISTANCE_IN);
- float verticalSwipeThresholdIn = DeviceConfig.getFloat(
+ float verticalSwipeThresholdIn = deviceConfigProxy.getFloat(
DeviceConfig.NAMESPACE_SYSTEMUI,
BRIGHTLINE_FALSING_DISTANCE_VERTICAL_SWIPE_THRESHOLD_IN,
VERTICAL_SWIPE_THRESHOLD_DISTANCE_IN);
- float screenFractionMaxDistance = DeviceConfig.getFloat(
+ float screenFractionMaxDistance = deviceConfigProxy.getFloat(
DeviceConfig.NAMESPACE_SYSTEMUI,
BRIGHTLINE_FALSING_DISTANCE_SCREEN_FRACTION_MAX_DISTANCE,
SCREEN_FRACTION_MAX_DISTANCE);
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/brightline/ProximityClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/brightline/ProximityClassifier.java
index 2644bf9f26ce..182704726129 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/brightline/ProximityClassifier.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/brightline/ProximityClassifier.java
@@ -24,6 +24,8 @@ import android.hardware.SensorEvent;
import android.provider.DeviceConfig;
import android.view.MotionEvent;
+import com.android.systemui.util.DeviceConfigProxy;
+
/**
* False touch if proximity sensor is covered for more than a certain percentage of the gesture.
@@ -44,11 +46,11 @@ class ProximityClassifier extends FalsingClassifier {
private float mPercentNear;
ProximityClassifier(DistanceClassifier distanceClassifier,
- FalsingDataProvider dataProvider) {
+ FalsingDataProvider dataProvider, DeviceConfigProxy deviceConfigProxy) {
super(dataProvider);
this.mDistanceClassifier = distanceClassifier;
- mPercentCoveredThreshold = DeviceConfig.getFloat(
+ mPercentCoveredThreshold = deviceConfigProxy.getFloat(
DeviceConfig.NAMESPACE_SYSTEMUI,
BRIGHTLINE_FALSING_PROXIMITY_PERCENT_COVERED_THRESHOLD,
PERCENT_COVERED_THRESHOLD);
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/brightline/ZigZagClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/brightline/ZigZagClassifier.java
index 82ae30ac4bdf..a0da988b27b5 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/brightline/ZigZagClassifier.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/brightline/ZigZagClassifier.java
@@ -25,6 +25,8 @@ import android.graphics.Point;
import android.provider.DeviceConfig;
import android.view.MotionEvent;
+import com.android.systemui.util.DeviceConfigProxy;
+
import java.util.ArrayList;
import java.util.List;
@@ -48,25 +50,25 @@ class ZigZagClassifier extends FalsingClassifier {
private final float mMaxXSecondaryDeviance;
private final float mMaxYSecondaryDeviance;
- ZigZagClassifier(FalsingDataProvider dataProvider) {
+ ZigZagClassifier(FalsingDataProvider dataProvider, DeviceConfigProxy deviceConfigProxy) {
super(dataProvider);
- mMaxXPrimaryDeviance = DeviceConfig.getFloat(
+ mMaxXPrimaryDeviance = deviceConfigProxy.getFloat(
DeviceConfig.NAMESPACE_SYSTEMUI,
BRIGHTLINE_FALSING_ZIGZAG_X_PRIMARY_DEVIANCE,
MAX_X_PRIMARY_DEVIANCE);
- mMaxYPrimaryDeviance = DeviceConfig.getFloat(
+ mMaxYPrimaryDeviance = deviceConfigProxy.getFloat(
DeviceConfig.NAMESPACE_SYSTEMUI,
BRIGHTLINE_FALSING_ZIGZAG_Y_PRIMARY_DEVIANCE,
MAX_Y_PRIMARY_DEVIANCE);
- mMaxXSecondaryDeviance = DeviceConfig.getFloat(
+ mMaxXSecondaryDeviance = deviceConfigProxy.getFloat(
DeviceConfig.NAMESPACE_SYSTEMUI,
BRIGHTLINE_FALSING_ZIGZAG_X_SECONDARY_DEVIANCE,
MAX_X_SECONDARY_DEVIANCE);
- mMaxYSecondaryDeviance = DeviceConfig.getFloat(
+ mMaxYSecondaryDeviance = deviceConfigProxy.getFloat(
DeviceConfig.NAMESPACE_SYSTEMUI,
BRIGHTLINE_FALSING_ZIGZAG_Y_SECONDARY_DEVIANCE,
MAX_Y_SECONDARY_DEVIANCE);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
index 9ac7ae98ecce..9178fda2b549 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
@@ -384,8 +384,7 @@ public class KeyguardIndicationController implements StateListener,
int userId = KeyguardUpdateMonitor.getCurrentUser();
String trustGrantedIndication = getTrustGrantedIndication();
String trustManagedIndication = getTrustManagedIndication();
- // TODO(b/140053632)
- if (!whitelistIpcs(() -> mUserManager.isUserUnlocked(userId))) {
+ if (!mKeyguardUpdateMonitor.isUserUnlocked(userId)) {
mTextView.switchIndication(com.android.internal.R.string.lockscreen_storage_locked);
mTextView.setTextColor(mInitialTextColorState);
} else if (!TextUtils.isEmpty(mTransientIndication)) {
@@ -757,6 +756,13 @@ public class KeyguardIndicationController implements StateListener,
}
@Override
+ public void onUserSwitchComplete(int userId) {
+ if (mVisible) {
+ updateIndication(false);
+ }
+ }
+
+ @Override
public void onUserUnlocked() {
if (mVisible) {
updateIndication(false);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
index 23b48141d0cc..ab9162ace817 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
@@ -19,7 +19,6 @@ package com.android.systemui.statusbar.phone;
import static android.view.accessibility.AccessibilityNodeInfo.ACTION_CLICK;
import static android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
-import static com.android.systemui.DejankUtils.whitelistIpcs;
import static com.android.systemui.doze.util.BurnInHelperKt.getBurnInOffset;
import static com.android.systemui.tuner.LockscreenFragment.LOCKSCREEN_LEFT_BUTTON;
import static com.android.systemui.tuner.LockscreenFragment.LOCKSCREEN_LEFT_UNLOCK;
@@ -117,6 +116,7 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
private static final int DOZE_ANIMATION_STAGGER_DELAY = 48;
private static final int DOZE_ANIMATION_ELEMENT_DURATION = 250;
+ private final UnlockMethodCache mUnlockMethodCache;
private KeyguardAffordanceView mRightAffordanceView;
private KeyguardAffordanceView mLeftAffordanceView;
private ViewGroup mIndicationArea;
@@ -129,7 +129,6 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
private View mCameraPreview;
private ActivityStarter mActivityStarter;
- private UnlockMethodCache mUnlockMethodCache;
private LockPatternUtils mLockPatternUtils;
private FlashlightController mFlashlightController;
private PreviewInflater mPreviewInflater;
@@ -185,6 +184,7 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
public KeyguardBottomAreaView(Context context, AttributeSet attrs, int defStyleAttr,
int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
+ mUnlockMethodCache = UnlockMethodCache.getInstance(getContext());
}
private AccessibilityDelegate mAccessibilityDelegate = new AccessibilityDelegate() {
@@ -242,8 +242,6 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
mBurnInYOffset = getResources().getDimensionPixelSize(
R.dimen.default_burn_in_prevention_offset);
updateCameraVisibility();
- mUnlockMethodCache = UnlockMethodCache.getInstance(getContext());
- mUnlockMethodCache.addListener(this);
setClipChildren(false);
setClipToPadding(false);
inflateCameraPreview();
@@ -281,11 +279,13 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
getContext().registerReceiverAsUser(mDevicePolicyReceiver,
UserHandle.ALL, filter, null, null);
KeyguardUpdateMonitor.getInstance(mContext).registerCallback(mUpdateMonitorCallback);
+ mUnlockMethodCache.addListener(this);
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
+ mUnlockMethodCache.removeListener(this);
mAccessibilityController.removeStateChangedCallback(this);
mRightExtension.destroy();
mLeftExtension.destroy();
@@ -365,11 +365,9 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
* Resolves the intent to launch the camera application.
*/
public ResolveInfo resolveCameraIntent() {
- // TODO(b/140057230)
- return whitelistIpcs(() ->
- mContext.getPackageManager().resolveActivityAsUser(getCameraIntent(),
- PackageManager.MATCH_DEFAULT_ONLY,
- KeyguardUpdateMonitor.getCurrentUser()));
+ return mContext.getPackageManager().resolveActivityAsUser(getCameraIntent(),
+ PackageManager.MATCH_DEFAULT_ONLY,
+ KeyguardUpdateMonitor.getCurrentUser());
}
private void updateCameraVisibility() {
@@ -806,11 +804,11 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
@Override
public IconState getIcon() {
- ResolveInfo resolved = resolveCameraIntent();
boolean isCameraDisabled = (mStatusBar != null) && !mStatusBar.isCameraAllowedByAdmin();
- mIconState.isVisible = !isCameraDisabled && resolved != null
+ mIconState.isVisible = !isCameraDisabled
&& getResources().getBoolean(R.bool.config_keyguardShowCameraAffordance)
- && mUserSetupComplete;
+ && mUserSetupComplete
+ && resolveCameraIntent() != null;
mIconState.drawable = mContext.getDrawable(R.drawable.ic_camera_alt_24dp);
mIconState.contentDescription =
mContext.getString(R.string.accessibility_camera_button);
@@ -822,9 +820,7 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
KeyguardUpdateMonitor updateMonitor = KeyguardUpdateMonitor.getInstance(mContext);
boolean canSkipBouncer = updateMonitor.getUserCanSkipBouncer(
KeyguardUpdateMonitor.getCurrentUser());
- // TODO(b/140057230)
- boolean secure = whitelistIpcs(() ->
- mLockPatternUtils.isSecure(KeyguardUpdateMonitor.getCurrentUser()));
+ boolean secure = mUnlockMethodCache.isMethodSecure();
return (secure && !canSkipBouncer) ? SECURE_CAMERA_INTENT : INSECURE_CAMERA_INTENT;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/util/DeviceConfigProxy.java b/packages/SystemUI/src/com/android/systemui/util/DeviceConfigProxy.java
new file mode 100644
index 000000000000..3a2172ae0fae
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/util/DeviceConfigProxy.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.util;
+
+import android.annotation.CallbackExecutor;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.provider.DeviceConfig;
+import android.provider.Settings;
+
+import java.util.concurrent.Executor;
+
+import javax.inject.Inject;
+
+/**
+ * Wrapper around DeviceConfig useful for testing.
+ */
+public class DeviceConfigProxy {
+ @Inject
+ public DeviceConfigProxy() {
+ }
+
+ /**
+ * Wrapped version of {@link DeviceConfig#addOnPropertiesChangedListener}.
+ */
+ public void addOnPropertiesChangedListener(
+ @NonNull String namespace,
+ @NonNull @CallbackExecutor Executor executor,
+ @NonNull DeviceConfig.OnPropertiesChangedListener onPropertiesChangedListener) {
+ DeviceConfig.addOnPropertiesChangedListener(
+ namespace, executor, onPropertiesChangedListener);
+ }
+
+ /**
+ * Wrapped version of {@link DeviceConfig#enforceReadPermission}.
+ */
+ public void enforceReadPermission(Context context, String namespace) {
+ DeviceConfig.enforceReadPermission(context, namespace);
+ }
+
+ /**
+ * Wrapped version of {@link DeviceConfig#getBoolean}.
+ */
+ public boolean getBoolean(
+ @NonNull String namespace, @NonNull String name, boolean defaultValue) {
+ return DeviceConfig.getBoolean(namespace, name, defaultValue);
+ }
+
+ /**
+ * Wrapped version of {@link DeviceConfig#getFloat}.
+ */
+ public float getFloat(
+ @NonNull String namespace, @NonNull String name, float defaultValue) {
+ return DeviceConfig.getFloat(namespace, name, defaultValue);
+ }
+
+ /**
+ * Wrapped version of {@link DeviceConfig#getInt}.
+ */
+ public int getInt(@NonNull String namespace, @NonNull String name, int defaultValue) {
+ return DeviceConfig.getInt(namespace, name, defaultValue);
+ }
+
+ /**
+ * Wrapped version of {@link DeviceConfig#getLong}.
+ */
+ public long getLong(@NonNull String namespace, @NonNull String name, long defaultValue) {
+ return DeviceConfig.getLong(namespace, name, defaultValue);
+
+ }
+
+ /**
+ * Wrapped version of {@link DeviceConfig#getProperty}.
+ */
+ public String getProperty(@NonNull String namespace, @NonNull String name) {
+ return DeviceConfig.getProperty(namespace, name);
+ }
+
+ /**
+ * Wrapped version of {@link DeviceConfig#getString}.
+ */
+ public String getString(
+ @NonNull String namespace, @NonNull String name, @Nullable String defaultValue) {
+ return DeviceConfig.getString(namespace, name, defaultValue);
+ }
+
+ /**
+ * Wrapped version of {@link DeviceConfig#removeOnPropertiesChangedListener}.
+ *
+ * Like {@link #addOnPropertiesChangedListener}, this operates on a callback type that
+ * wraps the original callback type provided by {@link DeviceConfig}.
+ */
+ public void removeOnPropertiesChangedListener(
+ @NonNull DeviceConfig.OnPropertiesChangedListener onPropertiesChangedListener) {
+ DeviceConfig.removeOnPropertiesChangedListener(onPropertiesChangedListener);
+ }
+
+ /**
+ * Wrapped version of {@link DeviceConfig#resetToDefaults}.
+ */
+ public void resetToDefaults(@Settings.ResetMode int resetMode,
+ @Nullable String namespace) {
+ DeviceConfig.resetToDefaults(resetMode, namespace);
+ }
+
+ /**
+ * Wrapped version of {@link DeviceConfig#setProperty}.
+ */
+ public boolean setProperty(
+ @NonNull String namespace,
+ @NonNull String name,
+ @Nullable String value,
+ boolean makeDefault) {
+ return DeviceConfig.setProperty(namespace, name, value, makeDefault);
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
index a3cb6c05ca7a..fce79c373c36 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
@@ -477,6 +477,16 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
assertThat(listToVerify.get(0)).isEqualTo(TEST_SUBSCRIPTION_2);
}
+ @Test
+ public void testIsUserUnlocked() {
+ // mUserManager will report the user as unlocked on @Before
+ assertThat(mKeyguardUpdateMonitor.isUserUnlocked(KeyguardUpdateMonitor.getCurrentUser()))
+ .isTrue();
+ // Invalid user should not be unlocked.
+ int randomUser = 99;
+ assertThat(mKeyguardUpdateMonitor.isUserUnlocked(randomUser)).isFalse();
+ }
+
private Intent putPhoneInfo(Intent intent, Bundle data, Boolean simInited) {
int subscription = simInited
? 1/* mock subid=1 */ : SubscriptionManager.DUMMY_SUBSCRIPTION_ID_BASE;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingManagerProxyTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingManagerProxyTest.java
index 7ea6493da83d..2073ae17784c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingManagerProxyTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingManagerProxyTest.java
@@ -31,6 +31,8 @@ import androidx.test.filters.SmallTest;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.classifier.brightline.BrightLineFalsingManager;
import com.android.systemui.shared.plugins.PluginManager;
+import com.android.systemui.util.DeviceConfigProxy;
+import com.android.systemui.util.DeviceConfigProxyFake;
import org.junit.After;
import org.junit.Before;
@@ -45,8 +47,9 @@ import org.mockito.MockitoAnnotations;
public class FalsingManagerProxyTest extends SysuiTestCase {
@Mock
PluginManager mPluginManager;
- private boolean mDefaultConfigValue;
private Handler mHandler;
+ private FalsingManagerProxy mProxy;
+ private DeviceConfigProxy mDeviceConfig;
private TestableLooper mTestableLooper;
@Before
@@ -54,50 +57,47 @@ public class FalsingManagerProxyTest extends SysuiTestCase {
MockitoAnnotations.initMocks(this);
mTestableLooper = TestableLooper.get(this);
mHandler = new Handler(mTestableLooper.getLooper());
- mDefaultConfigValue = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_SYSTEMUI,
- BRIGHTLINE_FALSING_MANAGER_ENABLED, false);
- // In case it runs on a device where it's been set to true, set it to false by hand.
- DeviceConfig.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI,
+ mDeviceConfig = new DeviceConfigProxyFake();
+ mDeviceConfig.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI,
BRIGHTLINE_FALSING_MANAGER_ENABLED, "false", false);
}
@After
public void tearDown() {
- DeviceConfig.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI,
- BRIGHTLINE_FALSING_MANAGER_ENABLED, mDefaultConfigValue ? "true" : "false", false);
+ if (mProxy != null) {
+ mProxy.cleanup();
+ }
}
@Test
public void test_brightLineFalsingManagerDisabled() {
- FalsingManagerProxy proxy = new FalsingManagerProxy(getContext(), mPluginManager, mHandler);
-
- assertThat(proxy.getInternalFalsingManager(), instanceOf(FalsingManagerImpl.class));
+ mProxy = new FalsingManagerProxy(getContext(), mPluginManager, mHandler, mDeviceConfig);
+ assertThat(mProxy.getInternalFalsingManager(), instanceOf(FalsingManagerImpl.class));
}
@Test
- public void test_brightLineFalsingManagerEnabled() {
- DeviceConfig.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI,
+ public void test_brightLineFalsingManagerEnabled() throws InterruptedException {
+ mDeviceConfig.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI,
BRIGHTLINE_FALSING_MANAGER_ENABLED, "true", false);
- FalsingManagerProxy proxy = new FalsingManagerProxy(getContext(), mPluginManager, mHandler);
-
- assertThat(proxy.getInternalFalsingManager(), instanceOf(BrightLineFalsingManager.class));
+ mTestableLooper.processAllMessages();
+ mProxy = new FalsingManagerProxy(getContext(), mPluginManager, mHandler, mDeviceConfig);
+ assertThat(mProxy.getInternalFalsingManager(), instanceOf(BrightLineFalsingManager.class));
}
@Test
- public void test_brightLineFalsingManagerToggled() {
- FalsingManagerProxy proxy = new FalsingManagerProxy(getContext(), mPluginManager, mHandler);
- assertThat(proxy.getInternalFalsingManager(), instanceOf(FalsingManagerImpl.class));
+ public void test_brightLineFalsingManagerToggled() throws InterruptedException {
+ mProxy = new FalsingManagerProxy(getContext(), mPluginManager, mHandler, mDeviceConfig);
+ assertThat(mProxy.getInternalFalsingManager(), instanceOf(FalsingManagerImpl.class));
- DeviceConfig.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI,
+ mDeviceConfig.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI,
BRIGHTLINE_FALSING_MANAGER_ENABLED, "true", false);
mTestableLooper.processAllMessages();
- proxy.setupFalsingManager(getContext());
- assertThat(proxy.getInternalFalsingManager(), instanceOf(BrightLineFalsingManager.class));
+ assertThat(mProxy.getInternalFalsingManager(),
+ instanceOf(BrightLineFalsingManager.class));
- DeviceConfig.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI,
+ mDeviceConfig.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI,
BRIGHTLINE_FALSING_MANAGER_ENABLED, "false", false);
mTestableLooper.processAllMessages();
- proxy.setupFalsingManager(getContext());
- assertThat(proxy.getInternalFalsingManager(), instanceOf(FalsingManagerImpl.class));
+ assertThat(mProxy.getInternalFalsingManager(), instanceOf(FalsingManagerImpl.class));
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/DiagonalClassifierTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/DiagonalClassifierTest.java
index b45d3f2855ee..afe4200a3a43 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/DiagonalClassifierTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/DiagonalClassifierTest.java
@@ -28,6 +28,8 @@ import android.testing.TestableLooper;
import androidx.test.filters.SmallTest;
+import com.android.systemui.util.DeviceConfigProxyFake;
+
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -58,7 +60,7 @@ public class DiagonalClassifierTest extends ClassifierTest {
public void setup() {
super.setup();
MockitoAnnotations.initMocks(this);
- mClassifier = new DiagonalClassifier(mDataProvider);
+ mClassifier = new DiagonalClassifier(mDataProvider, new DeviceConfigProxyFake());
}
@After
diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/DistanceClassifierTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/DistanceClassifierTest.java
index 805bb91591e5..f0f5fc719272 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/DistanceClassifierTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/DistanceClassifierTest.java
@@ -24,6 +24,8 @@ import android.testing.TestableLooper;
import androidx.test.filters.SmallTest;
+import com.android.systemui.util.DeviceConfigProxyFake;
+
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -41,7 +43,7 @@ public class DistanceClassifierTest extends ClassifierTest {
public void setup() {
super.setup();
mDataProvider = getDataProvider();
- mClassifier = new DistanceClassifier(mDataProvider);
+ mClassifier = new DistanceClassifier(mDataProvider, new DeviceConfigProxyFake());
}
@After
diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/ProximityClassifierTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/ProximityClassifierTest.java
index a6cabbf49458..c76fe74b1af7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/ProximityClassifierTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/ProximityClassifierTest.java
@@ -31,6 +31,8 @@ import android.view.MotionEvent;
import androidx.test.filters.SmallTest;
+import com.android.systemui.util.DeviceConfigProxyFake;
+
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -60,7 +62,8 @@ public class ProximityClassifierTest extends ClassifierTest {
MockitoAnnotations.initMocks(this);
when(mDataProvider.getInteractionType()).thenReturn(GENERIC);
when(mDistanceClassifier.isLongSwipe()).thenReturn(false);
- mClassifier = new ProximityClassifier(mDistanceClassifier, mDataProvider);
+ mClassifier = new ProximityClassifier(
+ mDistanceClassifier, mDataProvider, new DeviceConfigProxyFake());
}
@After
diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/ZigZagClassifierTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/ZigZagClassifierTest.java
index fb4c1ec11faa..387c0daad399 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/ZigZagClassifierTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/ZigZagClassifierTest.java
@@ -24,6 +24,8 @@ import android.testing.TestableLooper;
import androidx.test.filters.SmallTest;
+import com.android.systemui.util.DeviceConfigProxyFake;
+
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -41,7 +43,7 @@ public class ZigZagClassifierTest extends ClassifierTest {
@Before
public void setup() {
super.setup();
- mClassifier = new ZigZagClassifier(getDataProvider());
+ mClassifier = new ZigZagClassifier(getDataProvider(), new DeviceConfigProxyFake());
}
@After
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java
index daee55bd3d61..2427cfc77f39 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java
@@ -268,12 +268,18 @@ public class KeyguardIndicationControllerTest extends SysuiTestCase {
public void unlockMethodCache_listenerUpdatesIndication() {
createController();
String restingIndication = "Resting indication";
+
+ mController.setVisible(true);
+ assertThat(mTextView.getText()).isEqualTo(
+ mContext.getString(com.android.internal.R.string.lockscreen_storage_locked));
+
when(mKeyguardUpdateMonitor.getUserHasTrust(anyInt())).thenReturn(true);
+ when(mKeyguardUpdateMonitor.isUserUnlocked(anyInt())).thenReturn(true);
mController.setRestingIndication(restingIndication);
- mController.setVisible(true);
assertThat(mTextView.getText()).isEqualTo(mController.getTrustGrantedIndication());
reset(mKeyguardUpdateMonitor);
+ when(mKeyguardUpdateMonitor.isUserUnlocked(anyInt())).thenReturn(true);
when(mKeyguardUpdateMonitor.getUserHasTrust(anyInt())).thenReturn(false);
mController.onUnlockMethodStateChanged();
assertThat(mTextView.getText()).isEqualTo(restingIndication);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/DeviceConfigProxyFake.java b/packages/SystemUI/tests/src/com/android/systemui/util/DeviceConfigProxyFake.java
new file mode 100644
index 000000000000..426aba03d5d8
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/util/DeviceConfigProxyFake.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.util;
+
+import android.content.Context;
+import android.provider.DeviceConfig;
+import android.provider.DeviceConfig.OnPropertiesChangedListener;
+import android.provider.DeviceConfig.Properties;
+import android.util.Pair;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Executor;
+
+/**
+ * A Fake of {@link DeviceConfigProxy} useful for testing.
+ *
+ * No properties are set by default. No calls to {@link DeviceConfig} are made. Be sure to set any
+ * properties you rely on ahead of time in your test.
+ */
+public class DeviceConfigProxyFake extends DeviceConfigProxy {
+
+ private List<Pair<Executor, OnPropertiesChangedListener>> mListeners = new ArrayList<>();
+ private Map<String, Map<String, String>> mDefaultProperties = new HashMap<>();
+ private Map<String, Map<String, String>> mProperties = new HashMap<>();
+
+ public DeviceConfigProxyFake() {
+ }
+
+ @Override
+ public void addOnPropertiesChangedListener(
+ String namespace, Executor executor,
+ OnPropertiesChangedListener onPropertiesChangedListener) {
+ mListeners.add(Pair.create(executor, onPropertiesChangedListener));
+ }
+
+ @Override
+ public void removeOnPropertiesChangedListener(
+ OnPropertiesChangedListener onPropertiesChangedListener) {
+ mListeners.removeIf(listener -> {
+ if (listener == null) {
+ return false;
+ }
+ return listener.second.equals(onPropertiesChangedListener);
+ });
+ }
+
+ @Override
+ public boolean setProperty(String namespace, String name, String value, boolean makeDefault) {
+ setPropertyInternal(namespace, name, value, mProperties);
+ if (makeDefault) {
+ setPropertyInternal(namespace, name, value, mDefaultProperties);
+ }
+
+ for (Pair<Executor, OnPropertiesChangedListener> listener : mListeners) {
+ listener.first.execute(() -> listener.second.onPropertiesChanged(
+ new Properties(namespace, mProperties.get(namespace))));
+ }
+ return true;
+ }
+
+ private void setPropertyInternal(String namespace, String name, String value,
+ Map<String, Map<String, String>> properties) {
+ properties.putIfAbsent(namespace, new HashMap<>());
+ properties.get(namespace).put(name, value);
+ }
+
+ @Override
+ public void enforceReadPermission(Context context, String namespace) {
+ // no-op
+ }
+
+ private Properties propsForNamespaceAndName(String namespace, String name) {
+ if (mProperties.containsKey(namespace) && mProperties.get(namespace).containsKey(name)) {
+ return new Properties(namespace, mProperties.get(namespace));
+ }
+ if (mDefaultProperties.containsKey(namespace)) {
+ return new Properties(namespace, mDefaultProperties.get(namespace));
+ }
+
+ return null;
+ }
+
+ @Override
+ public boolean getBoolean(String namespace, String name, boolean defaultValue) {
+ Properties props = propsForNamespaceAndName(namespace, name);
+ if (props != null) {
+ return props.getBoolean(name, defaultValue);
+ }
+
+ return defaultValue;
+ }
+
+ @Override
+ public int getInt(String namespace, String name, int defaultValue) {
+ Properties props = propsForNamespaceAndName(namespace, name);
+ if (props != null) {
+ return props.getInt(name, defaultValue);
+ }
+
+ return defaultValue;
+ }
+
+ @Override
+ public long getLong(String namespace, String name, long defaultValue) {
+ Properties props = propsForNamespaceAndName(namespace, name);
+ if (props != null) {
+ return props.getLong(name, defaultValue);
+ }
+
+ return defaultValue;
+ }
+
+ @Override
+ public String getProperty(String namespace, String name) {
+ return getString(namespace, name, null);
+ }
+
+ @Override
+ public String getString(String namespace, String name, String defaultValue) {
+ Properties props = propsForNamespaceAndName(namespace, name);
+ if (props != null) {
+ return props.getString(name, defaultValue);
+ }
+
+ return defaultValue;
+ }
+
+ @Override
+ public void resetToDefaults(int resetMode, String namespace) {
+ if (mProperties.containsKey(namespace)) {
+ mProperties.get(namespace).clear();
+ }
+ }
+}
diff --git a/services/Android.bp b/services/Android.bp
index 27f8d36894da..6953e862f68b 100644
--- a/services/Android.bp
+++ b/services/Android.bp
@@ -63,6 +63,5 @@ cc_library_shared {
platform_compat_config {
name: "services-platform-compat-config",
- prefix: "services",
src: ":services",
}
diff --git a/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java b/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java
index d8b7e3a25e04..a338b901d24c 100644
--- a/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java
+++ b/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java
@@ -66,12 +66,6 @@ public class TouchExplorer extends BaseEventStreamTransformation
// Tag for logging received events.
private static final String LOG_TAG = "TouchExplorer";
- // States this explorer can be in.
- private static final int STATE_TOUCH_EXPLORING = 0x00000001;
- private static final int STATE_DRAGGING = 0x00000002;
- private static final int STATE_DELEGATING = 0x00000004;
- private static final int STATE_GESTURE_DETECTING = 0x00000005;
-
// The maximum of the cosine between the vectors of two moving
// pointers so they can be considered moving in the same direction.
private static final float MAX_DRAGGING_ANGLE_COS = 0.525321989f; // cos(pi/4)
@@ -248,7 +242,13 @@ public class TouchExplorer extends BaseEventStreamTransformation
return;
}
- if (mState.isTouchExploring()) {
+ // TODO: extract the below functions into separate handlers for each state.
+ // Right now the number of functions and number of states make the code messy.
+ if (mState.isClear()) {
+ handleMotionEventStateClear(event, rawEvent, policyFlags);
+ } else if (mState.isTouchInteracting()) {
+ handleMotionEventStateTouchInteracting(event, rawEvent, policyFlags);
+ } else if (mState.isTouchExploring()) {
handleMotionEventStateTouchExploring(event, rawEvent, policyFlags);
} else if (mState.isDragging()) {
handleMotionEventStateDragging(event, policyFlags);
@@ -286,8 +286,8 @@ public class TouchExplorer extends BaseEventStreamTransformation
@Override
public void onDoubleTapAndHold(MotionEvent event, int policyFlags) {
- // Ignore the event if we aren't touch exploring.
- if (!mState.isTouchExploring()) {
+ // Ignore the event if we aren't touch interacting.
+ if (!mState.isTouchInteracting()) {
return;
}
@@ -304,8 +304,7 @@ public class TouchExplorer extends BaseEventStreamTransformation
@Override
public boolean onDoubleTap(MotionEvent event, int policyFlags) {
- // Ignore the event if we aren't touch exploring.
- if (!mState.isTouchExploring()) {
+ if (!mState.isTouchInteracting()) {
return false;
}
@@ -380,35 +379,26 @@ public class TouchExplorer extends BaseEventStreamTransformation
}
/**
- * Handles a motion event in touch exploring state.
- *
- * @param event The event to be handled.
- * @param rawEvent The raw (unmodified) motion event.
- * @param policyFlags The policy flags associated with the event.
+ * Handles a motion event in the clear state i.e. no fingers are touching the screen.
*/
- private void handleMotionEventStateTouchExploring(
+ private void handleMotionEventStateClear(
MotionEvent event, MotionEvent rawEvent, int policyFlags) {
switch (event.getActionMasked()) {
+ // The only way to leave the clear state is for a pointer to go down.
case MotionEvent.ACTION_DOWN:
- handleActionDownStateTouchExploring(event, policyFlags);
- break;
- case MotionEvent.ACTION_POINTER_DOWN:
- handleActionPointerDownStateTouchExploring();
- break;
- case MotionEvent.ACTION_MOVE:
- handleActionMoveStateTouchExploring(event, rawEvent, policyFlags);
+ handleActionDown(event, policyFlags);
break;
- case MotionEvent.ACTION_UP:
- handleActionUpStateTouchExploring(event, policyFlags);
+ default:
+ // Some other nonsensical event.
break;
}
}
/**
- * Handles ACTION_DOWN while in the default touch exploring state. This event represents the
+ * Handles ACTION_DOWN while in the clear or touch interacting states. This event represents the
* first finger touching the screen.
*/
- private void handleActionDownStateTouchExploring(MotionEvent event, int policyFlags) {
+ private void handleActionDown(MotionEvent event, int policyFlags) {
mAms.onTouchInteractionStart();
// If we still have not notified the user for the last
@@ -418,13 +408,13 @@ public class TouchExplorer extends BaseEventStreamTransformation
mSendHoverExitDelayed.cancel();
// If a touch exploration gesture is in progress send events for its end.
- if (mState.isTouchExplorationInProgress()) {
+ if (mState.isTouchExploring()) {
sendHoverExitAndTouchExplorationGestureEndIfNeeded(policyFlags);
}
// Avoid duplicated TYPE_TOUCH_INTERACTION_START event when 2nd tap of double
// tap.
- if (!mGestureDetector.firstTapDetected()) {
+ if (!mGestureDetector.firstTapDetected() && mState.isClear()) {
mSendTouchExplorationEndDelayed.forceSendAndRemove();
mSendTouchInteractionEndDelayed.forceSendAndRemove();
sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_INTERACTION_START);
@@ -433,13 +423,15 @@ public class TouchExplorer extends BaseEventStreamTransformation
mSendTouchInteractionEndDelayed.cancel();
}
- if (!mGestureDetector.firstTapDetected() && !mState.isTouchExplorationInProgress()) {
+ if (!mGestureDetector.firstTapDetected() && !mState.isTouchExploring()) {
if (!mSendHoverEnterAndMoveDelayed.isPending()) {
- // Deliver hover enter with a delay to have a chance
- // to detect what the user is trying to do.
+ // Queue a delayed transition to STATE_TOUCH_EXPLORING.
+ // If we do not detect that this is a gesture, delegation or drag the transition
+ // will fire by default.
+ // The idea is to avoid getting stuck in STATE_TOUCH_INTERACTING
final int pointerId = mReceivedPointerTracker.getPrimaryPointerId();
final int pointerIdBits = (1 << pointerId);
- mSendHoverEnterAndMoveDelayed.post(event, true, pointerIdBits, policyFlags);
+ mSendHoverEnterAndMoveDelayed.post(event, pointerIdBits, policyFlags);
} else {
// Cache the event until we discern exploration from gesturing.
mSendHoverEnterAndMoveDelayed.addEvent(event);
@@ -448,10 +440,64 @@ public class TouchExplorer extends BaseEventStreamTransformation
}
/**
+ * Handles a motion event in touch interacting state.
+ *
+ * @param event The event to be handled.
+ * @param rawEvent The raw (unmodified) motion event.
+ * @param policyFlags The policy flags associated with the event.
+ */
+ private void handleMotionEventStateTouchInteracting(
+ MotionEvent event, MotionEvent rawEvent, int policyFlags) {
+ switch (event.getActionMasked()) {
+ case MotionEvent.ACTION_DOWN:
+ // Continue the previous interaction.
+ mSendTouchInteractionEndDelayed.cancel();
+ handleActionDown(event, policyFlags);
+ break;
+ case MotionEvent.ACTION_POINTER_DOWN:
+ handleActionPointerDown();
+ break;
+ case MotionEvent.ACTION_MOVE:
+ handleActionMoveStateTouchInteracting(event, rawEvent, policyFlags);
+ break;
+ case MotionEvent.ACTION_UP:
+ handleActionUp(event, policyFlags);
+ break;
+ }
+ }
+
+ /**
+ * Handles a motion event in touch exploring state.
+ *
+ * @param event The event to be handled.
+ * @param rawEvent The raw (unmodified) motion event.
+ * @param policyFlags The policy flags associated with the event.
+ */
+ private void handleMotionEventStateTouchExploring(
+ MotionEvent event, MotionEvent rawEvent, int policyFlags) {
+ switch (event.getActionMasked()) {
+ case MotionEvent.ACTION_DOWN:
+ // We should have already received ACTION_DOWN. Ignore.
+ break;
+ case MotionEvent.ACTION_POINTER_DOWN:
+ handleActionPointerDown();
+ break;
+ case MotionEvent.ACTION_MOVE:
+ handleActionMoveStateTouchExploring(event, rawEvent, policyFlags);
+ break;
+ case MotionEvent.ACTION_UP:
+ handleActionUp(event, policyFlags);
+ break;
+ default:
+ break;
+ }
+ }
+
+ /**
* Handles ACTION_POINTER_DOWN when in the touch exploring state. This event represents an
* additional finger touching the screen.
*/
- private void handleActionPointerDownStateTouchExploring() {
+ private void handleActionPointerDown() {
// Another finger down means that if we have not started to deliver
// hover events, we will not have to. The code for ACTION_MOVE will
// decide what we will actually do next.
@@ -459,10 +505,10 @@ public class TouchExplorer extends BaseEventStreamTransformation
mSendHoverExitDelayed.cancel();
}
/**
- * Handles ACTION_MOVE while in the initial touch exploring state. This is where transitions to
+ * Handles ACTION_MOVE while in the touch interacting state. This is where transitions to
* delegating and dragging states are handled.
*/
- private void handleActionMoveStateTouchExploring(
+ private void handleActionMoveStateTouchInteracting(
MotionEvent event, MotionEvent rawEvent, int policyFlags) {
final int pointerId = mReceivedPointerTracker.getPrimaryPointerId();
final int pointerIndex = event.findPointerIndex(pointerId);
@@ -474,41 +520,14 @@ public class TouchExplorer extends BaseEventStreamTransformation
if (mSendHoverEnterAndMoveDelayed.isPending()) {
// Cache the event until we discern exploration from gesturing.
mSendHoverEnterAndMoveDelayed.addEvent(event);
- } else if (mState.isTouchExplorationInProgress()) {
- sendTouchExplorationGestureStartAndHoverEnterIfNeeded(policyFlags);
- sendMotionEvent(
- event, MotionEvent.ACTION_HOVER_MOVE, pointerIdBits, policyFlags);
}
break;
case 2:
+ // Make sure we don't have any pending transitions to touch exploration
+ mSendHoverEnterAndMoveDelayed.cancel();
+ mSendHoverExitDelayed.cancel();
// More than one pointer so the user is not touch exploring
// and now we have to decide whether to delegate or drag.
- if (mSendHoverEnterAndMoveDelayed.isPending()) {
- // We have not started sending events so cancel
- // scheduled sending events.
- mSendHoverEnterAndMoveDelayed.cancel();
- mSendHoverExitDelayed.cancel();
- } else if (mState.isTouchExplorationInProgress()) {
- // If the user is touch exploring the second pointer may be
- // performing a double tap to activate an item without need
- // for the user to lift his exploring finger.
- // It is *important* to use the distance traveled by the pointers
- // on the screen which may or may not be magnified.
- final float deltaX =
- mReceivedPointerTracker.getReceivedPointerDownX(pointerId)
- - rawEvent.getX(pointerIndex);
- final float deltaY =
- mReceivedPointerTracker.getReceivedPointerDownY(pointerId)
- - rawEvent.getY(pointerIndex);
- final double moveDelta = Math.hypot(deltaX, deltaY);
- if (moveDelta < mDoubleTapSlop) {
- break;
- }
- // We are sending events so send exit and gesture
- // end since we transition to another state.
- sendHoverExitAndTouchExplorationGestureEndIfNeeded(policyFlags);
- }
-
// Remove move history before send injected non-move events
event = MotionEvent.obtainNoHistory(event);
if (isDraggingGesture(event)) {
@@ -525,19 +544,6 @@ public class TouchExplorer extends BaseEventStreamTransformation
}
break;
default:
- // More than one pointer so the user is not touch exploring
- // and now we have to decide whether to delegate or drag.
- if (mSendHoverEnterAndMoveDelayed.isPending()) {
- // We have not started sending events so cancel
- // scheduled sending events.
- mSendHoverEnterAndMoveDelayed.cancel();
- mSendHoverExitDelayed.cancel();
- } else {
- // We are sending events so send exit and gesture
- // end since we transition to another state.
- sendHoverExitAndTouchExplorationGestureEndIfNeeded(policyFlags);
- }
-
// More than two pointers are delegated to the view hierarchy.
mState.startDelegating();
event = MotionEvent.obtainNoHistory(event);
@@ -547,14 +553,13 @@ public class TouchExplorer extends BaseEventStreamTransformation
}
/**
- * Handles ACTION_UP while in the initial touch exploring state. This event represents all
- * fingers being lifted from the screen.
+ * Handles ACTION_UP while in the touch interacting state. This event represents all fingers
+ * being lifted from the screen.
*/
- private void handleActionUpStateTouchExploring(MotionEvent event, int policyFlags) {
+ private void handleActionUp(MotionEvent event, int policyFlags) {
mAms.onTouchInteractionEnd();
final int pointerId = event.getPointerId(event.getActionIndex());
final int pointerIdBits = (1 << pointerId);
-
if (mSendHoverEnterAndMoveDelayed.isPending()) {
// If we have not delivered the enter schedule an exit.
mSendHoverExitDelayed.post(event, pointerIdBits, policyFlags);
@@ -562,13 +567,69 @@ public class TouchExplorer extends BaseEventStreamTransformation
// The user is touch exploring so we send events for end.
sendHoverExitAndTouchExplorationGestureEndIfNeeded(policyFlags);
}
-
if (!mSendTouchInteractionEndDelayed.isPending()) {
mSendTouchInteractionEndDelayed.post();
}
}
/**
+ * Handles move events while touch exploring. this is also where we drag or delegate based on
+ * the number of fingers moving on the screen.
+ */
+ private void handleActionMoveStateTouchExploring(
+ MotionEvent event, MotionEvent rawEvent, int policyFlags) {
+ final int pointerId = mReceivedPointerTracker.getPrimaryPointerId();
+ final int pointerIdBits = (1 << pointerId);
+ final int pointerIndex = event.findPointerIndex(pointerId);
+ switch (event.getPointerCount()) {
+ case 1:
+ // Touch exploration.
+ sendTouchExplorationGestureStartAndHoverEnterIfNeeded(policyFlags);
+ sendMotionEvent(event, MotionEvent.ACTION_HOVER_MOVE, pointerIdBits, policyFlags);
+ break;
+ case 2:
+ if (mSendHoverEnterAndMoveDelayed.isPending()) {
+ // We have not started sending events so cancel
+ // scheduled sending events.
+ mSendHoverEnterAndMoveDelayed.cancel();
+ mSendHoverExitDelayed.cancel();
+ }
+ // If the user is touch exploring the second pointer may be
+ // performing a double tap to activate an item without need
+ // for the user to lift his exploring finger.
+ // It is *important* to use the distance traveled by the pointers
+ // on the screen which may or may not be magnified.
+ final float deltaX =
+ mReceivedPointerTracker.getReceivedPointerDownX(pointerId)
+ - rawEvent.getX(pointerIndex);
+ final float deltaY =
+ mReceivedPointerTracker.getReceivedPointerDownY(pointerId)
+ - rawEvent.getY(pointerIndex);
+ final double moveDelta = Math.hypot(deltaX, deltaY);
+ if (moveDelta > mDoubleTapSlop) {
+ // The user is trying to either delegate or drag.
+ handleActionMoveStateTouchInteracting(event, rawEvent, policyFlags);
+ } else {
+ // Otherwise the double tap will be handled by the gesture detector.
+ sendHoverExitAndTouchExplorationGestureEndIfNeeded(policyFlags);
+ }
+ break;
+ default:
+ // Three or more fingers is something other than touch exploration.
+ if (mSendHoverEnterAndMoveDelayed.isPending()) {
+ // We have not started sending events so cancel
+ // scheduled sending events.
+ mSendHoverEnterAndMoveDelayed.cancel();
+ mSendHoverExitDelayed.cancel();
+ } else {
+ sendHoverExitAndTouchExplorationGestureEndIfNeeded(policyFlags);
+ }
+ handleActionMoveStateTouchInteracting(event, rawEvent, policyFlags);
+ break;
+ }
+ }
+
+ /**
* Handles a motion event in dragging state.
*
* @param event The event to be handled.
@@ -670,7 +731,6 @@ public class TouchExplorer extends BaseEventStreamTransformation
// Send an event to the end of the drag gesture.
sendMotionEvent(event, MotionEvent.ACTION_UP, pointerIdBits, policyFlags);
}
- mState.startTouchExploring();
} break;
}
}
@@ -697,7 +757,6 @@ public class TouchExplorer extends BaseEventStreamTransformation
mAms.onTouchInteractionEnd();
sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_INTERACTION_END);
- mState.startTouchExploring();
} break;
default: {
// Deliver the event.
@@ -717,7 +776,6 @@ public class TouchExplorer extends BaseEventStreamTransformation
}
mExitGestureDetectionModeDelayed.cancel();
- mState.startTouchExploring();
}
/**
@@ -731,8 +789,13 @@ public class TouchExplorer extends BaseEventStreamTransformation
AccessibilityEvent event = AccessibilityEvent.obtain(type);
event.setWindowId(mAms.getActiveWindowId());
accessibilityManager.sendAccessibilityEvent(event);
- mState.onInjectedAccessibilityEvent(type);
+ if (DEBUG) {
+ Slog.d(
+ LOG_TAG,
+ "Sending accessibility event" + AccessibilityEvent.eventTypeToString(type));
+ }
}
+ mState.onInjectedAccessibilityEvent(type);
}
/**
@@ -915,6 +978,10 @@ public class TouchExplorer extends BaseEventStreamTransformation
MAX_DRAGGING_ANGLE_COS);
}
+ public TouchState getState() {
+ return mState;
+ }
+
/**
* Class for delayed exiting from gesture detecting mode.
*/
@@ -947,8 +1014,7 @@ public class TouchExplorer extends BaseEventStreamTransformation
private int mPointerIdBits;
private int mPolicyFlags;
- public void post(MotionEvent event, boolean touchExplorationInProgress,
- int pointerIdBits, int policyFlags) {
+ public void post(MotionEvent event, int pointerIdBits, int policyFlags) {
cancel();
addEvent(event);
mPointerIdBits = pointerIdBits;
diff --git a/services/accessibility/java/com/android/server/accessibility/gestures/TouchState.java b/services/accessibility/java/com/android/server/accessibility/gestures/TouchState.java
index 820c1a794635..17e969a1aa49 100644
--- a/services/accessibility/java/com/android/server/accessibility/gestures/TouchState.java
+++ b/services/accessibility/java/com/android/server/accessibility/gestures/TouchState.java
@@ -41,20 +41,33 @@ public class TouchState {
public static final int ALL_POINTER_ID_BITS = 0xFFFFFFFF;
// States that the touch explorer can be in.
- public static final int STATE_TOUCH_EXPLORING = 0x00000001;
- public static final int STATE_DRAGGING = 0x00000002;
- public static final int STATE_DELEGATING = 0x00000003;
- public static final int STATE_GESTURE_DETECTING = 0x00000004;
-
- @IntDef({STATE_TOUCH_EXPLORING, STATE_DRAGGING, STATE_DELEGATING, STATE_GESTURE_DETECTING})
+ // In the clear state the user is not touching the screen.
+ public static final int STATE_CLEAR = 0;
+ // The user is touching the screen and we are trying to figure out their intent.
+ // This state gets its name from the TYPE_TOUCH_INTERACTION start and end accessibility events.
+ public static final int STATE_TOUCH_INTERACTING = 1;
+ // The user is explicitly exploring the screen.
+ public static final int STATE_TOUCH_EXPLORING = 2;
+ // the user is dragging with two fingers.
+ public static final int STATE_DRAGGING = 3;
+ // The user is performing some other two finger gesture which we pass through to the view
+ // hierarchy as a one-finger gesture e.g. two-finger scrolling.
+ public static final int STATE_DELEGATING = 4;
+ // The user is performing something that might be a gesture.
+ public static final int STATE_GESTURE_DETECTING = 5;
+
+ @IntDef({
+ STATE_CLEAR,
+ STATE_TOUCH_INTERACTING,
+ STATE_TOUCH_EXPLORING,
+ STATE_DRAGGING,
+ STATE_DELEGATING,
+ STATE_GESTURE_DETECTING
+ })
public @interface State {}
// The current state of the touch explorer.
- private int mState = STATE_TOUCH_EXPLORING;
- // Whether touch exploration is in progress.
- // TODO: Add separate states to represent intend detection and actual touch exploration so that
- // only one variable describes the state.
- private boolean mTouchExplorationInProgress;
+ private int mState = STATE_CLEAR;
// Helper class to track received pointers.
// Todo: collapse or hide this class so multiple classes don't modify it.
private final ReceivedPointerTracker mReceivedPointerTracker;
@@ -69,8 +82,7 @@ public class TouchState {
/** Clears the internal shared state. */
public void clear() {
- mState = STATE_TOUCH_EXPLORING;
- mTouchExplorationInProgress = false;
+ setState(STATE_CLEAR);
// Reset the pointer trackers.
mReceivedPointerTracker.clear();
mInjectedPointerTracker.clear();
@@ -94,18 +106,33 @@ public class TouchState {
mReceivedPointerTracker.onMotionEvent(rawEvent);
}
- /**
- * Updates the state in response to an accessibility event being sent from TouchExplorer.
- *
- * @param type The event type.
- */
public void onInjectedAccessibilityEvent(int type) {
+ // The below state transitions go here because the related events are often sent on a
+ // delay.
+ // This allows state to accurately reflect the state in the moment.
+ // TODO: replaced the delayed event senders with delayed state transitions
+ // so that state transitions trigger events rather than events triggering state
+ // transitions.
switch (type) {
+ case AccessibilityEvent.TYPE_TOUCH_INTERACTION_START:
+ startTouchInteracting();
+ break;
+ case AccessibilityEvent.TYPE_TOUCH_INTERACTION_END:
+ clear();
+ break;
case AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_START:
- mTouchExplorationInProgress = true;
+ startTouchExploring();
break;
case AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_END:
- mTouchExplorationInProgress = false;
+ startTouchInteracting();
+ break;
+ case AccessibilityEvent.TYPE_GESTURE_DETECTION_START:
+ startGestureDetecting();
+ break;
+ case AccessibilityEvent.TYPE_GESTURE_DETECTION_END:
+ startTouchInteracting();
+ break;
+ default:
break;
}
}
@@ -117,6 +144,7 @@ public class TouchState {
/** Transitions to a new state. */
public void setState(@State int state) {
+ if (mState == state) return;
if (DEBUG) {
Slog.i(LOG_TAG, getStateSymbolicName(mState) + "->" + getStateSymbolicName(state));
}
@@ -159,26 +187,32 @@ public class TouchState {
setState(STATE_DRAGGING);
}
- public boolean isTouchExplorationInProgress() {
- return mTouchExplorationInProgress;
+ public boolean isTouchInteracting() {
+ return mState == STATE_TOUCH_INTERACTING;
}
- public void setTouchExplorationInProgress(boolean touchExplorationInProgress) {
- mTouchExplorationInProgress = touchExplorationInProgress;
+ /**
+ * Transitions to the touch interacting state, where we attempt to figure out what the user is
+ * doing.
+ */
+ public void startTouchInteracting() {
+ setState(STATE_TOUCH_INTERACTING);
}
+ public boolean isClear() {
+ return mState == STATE_CLEAR;
+ }
/** Returns a string representation of the current state. */
public String toString() {
- return "TouchState { "
- + "mState: "
- + getStateSymbolicName(mState)
- + ", mTouchExplorationInProgress"
- + mTouchExplorationInProgress
- + " }";
+ return "TouchState { " + "mState: " + getStateSymbolicName(mState) + " }";
}
/** Returns a string representation of the specified state. */
public static String getStateSymbolicName(int state) {
switch (state) {
+ case STATE_CLEAR:
+ return "STATE_CLEAR";
+ case STATE_TOUCH_INTERACTING:
+ return "STATE_TOUCH_INTERACTING";
case STATE_TOUCH_EXPLORING:
return "STATE_TOUCH_EXPLORING";
case STATE_DRAGGING:
diff --git a/services/appprediction/java/com/android/server/appprediction/AppPredictionManagerService.java b/services/appprediction/java/com/android/server/appprediction/AppPredictionManagerService.java
index d7e68f896c6c..5844f9873001 100644
--- a/services/appprediction/java/com/android/server/appprediction/AppPredictionManagerService.java
+++ b/services/appprediction/java/com/android/server/appprediction/AppPredictionManagerService.java
@@ -23,6 +23,7 @@ import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.UserIdInt;
import android.app.prediction.AppPredictionContext;
import android.app.prediction.AppPredictionSessionId;
import android.app.prediction.AppTargetEvent;
@@ -61,7 +62,8 @@ public class AppPredictionManagerService extends
public AppPredictionManagerService(Context context) {
super(context, new FrameworkResourcesServiceNameResolver(context,
- com.android.internal.R.string.config_defaultAppPredictionService), null);
+ com.android.internal.R.string.config_defaultAppPredictionService), null,
+ PACKAGE_UPDATE_POLICY_NO_REFRESH | PACKAGE_RESTART_POLICY_NO_REFRESH);
mActivityTaskManagerInternal = LocalServices.getService(ActivityTaskManagerInternal.class);
}
@@ -80,6 +82,22 @@ public class AppPredictionManagerService extends
getContext().enforceCallingPermission(MANAGE_APP_PREDICTIONS, TAG);
}
+ @Override // from AbstractMasterSystemService
+ protected void onServicePackageUpdatedLocked(@UserIdInt int userId) {
+ final AppPredictionPerUserService service = peekServiceForUserLocked(userId);
+ if (service != null) {
+ service.onPackageUpdatedLocked();
+ }
+ }
+
+ @Override // from AbstractMasterSystemService
+ protected void onServicePackageRestartedLocked(@UserIdInt int userId) {
+ final AppPredictionPerUserService service = peekServiceForUserLocked(userId);
+ if (service != null) {
+ service.onPackageRestartedLocked();
+ }
+ }
+
@Override
protected int getMaximumTemporaryServiceDurationMs() {
return MAX_TEMP_SERVICE_DURATION_MS;
diff --git a/services/appprediction/java/com/android/server/appprediction/AppPredictionPerUserService.java b/services/appprediction/java/com/android/server/appprediction/AppPredictionPerUserService.java
index 03c4542a50d4..4f49fb7578a1 100644
--- a/services/appprediction/java/com/android/server/appprediction/AppPredictionPerUserService.java
+++ b/services/appprediction/java/com/android/server/appprediction/AppPredictionPerUserService.java
@@ -251,6 +251,40 @@ public class AppPredictionPerUserService extends
// Do nothing, eventually the system will bind to the remote service again...
}
+ void onPackageUpdatedLocked() {
+ if (isDebug()) {
+ Slog.v(TAG, "onPackageUpdatedLocked()");
+ }
+ destroyAndRebindRemoteService();
+ }
+
+ void onPackageRestartedLocked() {
+ if (isDebug()) {
+ Slog.v(TAG, "onPackageRestartedLocked()");
+ }
+ destroyAndRebindRemoteService();
+ }
+
+ private void destroyAndRebindRemoteService() {
+ if (mRemoteService == null) {
+ return;
+ }
+
+ if (isDebug()) {
+ Slog.d(TAG, "Destroying the old remote service.");
+ }
+ mRemoteService.destroy();
+ mRemoteService = null;
+
+ mRemoteService = getRemoteServiceLocked();
+ if (mRemoteService != null) {
+ if (isDebug()) {
+ Slog.d(TAG, "Rebinding to the new remote service.");
+ }
+ mRemoteService.reconnect();
+ }
+ }
+
/**
* Called after the remote service connected, it's used to restore state from a 'zombie'
* service (i.e., after it died).
diff --git a/services/appprediction/java/com/android/server/appprediction/RemoteAppPredictionService.java b/services/appprediction/java/com/android/server/appprediction/RemoteAppPredictionService.java
index c82e7a012fff..04e0e7f7102f 100644
--- a/services/appprediction/java/com/android/server/appprediction/RemoteAppPredictionService.java
+++ b/services/appprediction/java/com/android/server/appprediction/RemoteAppPredictionService.java
@@ -135,6 +135,13 @@ public class RemoteAppPredictionService extends
}
/**
+ * Schedules a request to bind to the remote service.
+ */
+ public void reconnect() {
+ super.scheduleBind();
+ }
+
+ /**
* Failure callback
*/
public interface RemoteAppPredictionServiceCallbacks
diff --git a/services/core/java/com/android/server/compat/CompatConfig.java b/services/core/java/com/android/server/compat/CompatConfig.java
index 044e41789bb2..027e2fb5ccaa 100644
--- a/services/core/java/com/android/server/compat/CompatConfig.java
+++ b/services/core/java/com/android/server/compat/CompatConfig.java
@@ -47,11 +47,10 @@ import javax.xml.datatype.DatatypeConfigurationException;
public final class CompatConfig {
private static final String TAG = "CompatConfig";
- private static final String CONFIG_FILE_SUFFIX = "platform_compat_config.xml";
private static final CompatConfig sInstance = new CompatConfig().initConfigFromLib(
Environment.buildPath(
- Environment.getRootDirectory(), "etc", "sysconfig"));
+ Environment.getRootDirectory(), "etc", "compatconfig"));
@GuardedBy("mChanges")
private final LongSparseArray<CompatChange> mChanges = new LongSparseArray<>();
@@ -212,10 +211,9 @@ public final class CompatConfig {
return this;
}
for (File f : libraryDir.listFiles()) {
+ Slog.d(TAG, "Found a config file: " + f.getPath());
//TODO(b/138222363): Handle duplicate ids across config files.
- if (f.getPath().endsWith(CONFIG_FILE_SUFFIX)) {
- readConfig(f);
- }
+ readConfig(f);
}
return this;
}
@@ -223,7 +221,7 @@ public final class CompatConfig {
private void readConfig(File configFile) {
try (InputStream in = new BufferedInputStream(new FileInputStream(configFile))) {
for (Change change : XmlParser.read(in).getCompatChange()) {
- Slog.w(TAG, "Adding: " + change.toString());
+ Slog.d(TAG, "Adding: " + change.toString());
addChange(new CompatChange(change));
}
} catch (IOException | DatatypeConfigurationException | XmlPullParserException e) {
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index 4d5dc6aba937..2b849d69ae1c 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -297,6 +297,11 @@ public class HdmiControlService extends SystemService {
mHdmiControlBroadcastReceiver = new HdmiControlBroadcastReceiver();
@Nullable
+ // Save callback when the device is still under logcial address allocation
+ // Invoke once new local device is ready.
+ private IHdmiControlCallback mDisplayStatusCallback = null;
+
+ @Nullable
private HdmiCecController mCecController;
// HDMI port information. Stored in the unmodifiable list to keep the static information
@@ -763,6 +768,11 @@ public class HdmiControlService extends SystemService {
// Address allocation completed for all devices. Notify each device.
if (allocatingDevices.size() == ++finished[0]) {
mAddressAllocated = true;
+ // Reinvoke the saved display status callback once the local device is ready.
+ if (mDisplayStatusCallback != null) {
+ queryDisplayStatus(mDisplayStatusCallback);
+ mDisplayStatusCallback = null;
+ }
if (initiatedBy != INITIATED_BY_HOTPLUG) {
// In case of the hotplug we don't call onInitializeCecComplete()
// since we reallocate the logical address only.
@@ -2192,6 +2202,13 @@ public class HdmiControlService extends SystemService {
@ServiceThreadOnly
private void queryDisplayStatus(final IHdmiControlCallback callback) {
assertRunOnServiceThread();
+ if (!mAddressAllocated) {
+ mDisplayStatusCallback = callback;
+ Slog.d(TAG, "Local device is under address allocation. "
+ + "Queue display callback for later process.");
+ return;
+ }
+
HdmiCecLocalDevicePlayback source = playback();
if (source == null) {
Slog.w(TAG, "Local playback device not available");
diff --git a/services/core/java/com/android/server/infra/AbstractMasterSystemService.java b/services/core/java/com/android/server/infra/AbstractMasterSystemService.java
index a9c4d088f203..d71ffb770cc3 100644
--- a/services/core/java/com/android/server/infra/AbstractMasterSystemService.java
+++ b/services/core/java/com/android/server/infra/AbstractMasterSystemService.java
@@ -80,7 +80,7 @@ public abstract class AbstractMasterSystemService<M extends AbstractMasterSystem
S extends AbstractPerUserSystemService<S, M>> extends SystemService {
/** On a package update, does not refresh the per-user service in the cache. */
- public static final int PACKAGE_UPDATE_POLICY_NO_REFRESH = 0;
+ public static final int PACKAGE_UPDATE_POLICY_NO_REFRESH = 0x00000001;
/**
* On a package update, removes any existing per-user services in the cache.
@@ -88,20 +88,40 @@ public abstract class AbstractMasterSystemService<M extends AbstractMasterSystem
* <p>This does not immediately recreate these services. It is assumed they will be recreated
* for the next user request.
*/
- public static final int PACKAGE_UPDATE_POLICY_REFRESH_LAZY = 1;
+ public static final int PACKAGE_UPDATE_POLICY_REFRESH_LAZY = 0x00000002;
/**
* On a package update, removes and recreates any existing per-user services in the cache.
*/
- public static final int PACKAGE_UPDATE_POLICY_REFRESH_EAGER = 2;
+ public static final int PACKAGE_UPDATE_POLICY_REFRESH_EAGER = 0x00000004;
- @IntDef(flag = true, prefix = { "PACKAGE_UPDATE_POLICY_" }, value = {
+ /** On a package restart, does not refresh the per-user service in the cache. */
+ public static final int PACKAGE_RESTART_POLICY_NO_REFRESH = 0x00000010;
+
+ /**
+ * On a package restart, removes any existing per-user services in the cache.
+ *
+ * <p>This does not immediately recreate these services. It is assumed they will be recreated
+ * for the next user request.
+ */
+ public static final int PACKAGE_RESTART_POLICY_REFRESH_LAZY = 0x00000020;
+
+ /**
+ * On a package restart, removes and recreates any existing per-user services in the cache.
+ */
+ public static final int PACKAGE_RESTART_POLICY_REFRESH_EAGER = 0x00000040;
+
+ @IntDef(flag = true, prefix = { "PACKAGE_" }, value = {
PACKAGE_UPDATE_POLICY_NO_REFRESH,
PACKAGE_UPDATE_POLICY_REFRESH_LAZY,
- PACKAGE_UPDATE_POLICY_REFRESH_EAGER
+ PACKAGE_UPDATE_POLICY_REFRESH_EAGER,
+ PACKAGE_RESTART_POLICY_NO_REFRESH,
+ PACKAGE_RESTART_POLICY_REFRESH_LAZY,
+ PACKAGE_RESTART_POLICY_REFRESH_EAGER
})
+
@Retention(RetentionPolicy.SOURCE)
- public @interface PackageUpdatePolicy {}
+ public @interface ServicePackagePolicyFlags {}
/**
* Log tag
@@ -154,12 +174,10 @@ public abstract class AbstractMasterSystemService<M extends AbstractMasterSystem
private final SparseArray<S> mServicesCache = new SparseArray<>();
/**
- * Whether the per-user service should be removed from the cache when its apk is updated.
- *
- * <p>One of {@link #PACKAGE_UPDATE_POLICY_NO_REFRESH},
- * {@link #PACKAGE_UPDATE_POLICY_REFRESH_LAZY} or {@link #PACKAGE_UPDATE_POLICY_REFRESH_EAGER}.
+ * Value that determines whether the per-user service should be removed from the cache when its
+ * apk is updated or restarted.
*/
- private final @PackageUpdatePolicy int mPackageUpdatePolicy;
+ private final @ServicePackagePolicyFlags int mServicePackagePolicyFlags;
/**
* Name of the service packages whose APK are being updated, keyed by user id.
@@ -191,11 +209,11 @@ public abstract class AbstractMasterSystemService<M extends AbstractMasterSystem
@Nullable ServiceNameResolver serviceNameResolver,
@Nullable String disallowProperty) {
this(context, serviceNameResolver, disallowProperty,
- /*packageUpdatePolicy=*/ PACKAGE_UPDATE_POLICY_REFRESH_LAZY);
+ PACKAGE_UPDATE_POLICY_REFRESH_LAZY | PACKAGE_RESTART_POLICY_REFRESH_LAZY);
}
/**
- * Full constructor.
+ * Full Constructor.
*
* @param context system context.
* @param serviceNameResolver resolver for
@@ -204,19 +222,32 @@ public abstract class AbstractMasterSystemService<M extends AbstractMasterSystem
* @param disallowProperty when not {@code null}, defines a {@link UserManager} restriction that
* disables the service. <b>NOTE: </b> you'll also need to add it to
* {@code UserRestrictionsUtils.USER_RESTRICTIONS}.
- * @param packageUpdatePolicy when {@link #PACKAGE_UPDATE_POLICY_REFRESH_LAZY}, the
- * {@link AbstractPerUserSystemService} is removed from the cache when the service
- * package is updated; when {@link #PACKAGE_UPDATE_POLICY_REFRESH_EAGER}, the
- * {@link AbstractPerUserSystemService} is removed from the cache and immediately
- * re-added when the service package is updated; when
- * {@link #PACKAGE_UPDATE_POLICY_NO_REFRESH}, the service is untouched during the update.
+ * @param servicePackagePolicyFlags a combination of
+ * {@link #PACKAGE_UPDATE_POLICY_NO_REFRESH},
+ * {@link #PACKAGE_UPDATE_POLICY_REFRESH_LAZY},
+ * {@link #PACKAGE_UPDATE_POLICY_REFRESH_EAGER},
+ * {@link #PACKAGE_RESTART_POLICY_NO_REFRESH},
+ * {@link #PACKAGE_RESTART_POLICY_REFRESH_LAZY} or
+ * {@link #PACKAGE_RESTART_POLICY_REFRESH_EAGER}
*/
protected AbstractMasterSystemService(@NonNull Context context,
- @Nullable ServiceNameResolver serviceNameResolver,
- @Nullable String disallowProperty, @PackageUpdatePolicy int packageUpdatePolicy) {
+ @Nullable ServiceNameResolver serviceNameResolver, @Nullable String disallowProperty,
+ @ServicePackagePolicyFlags int servicePackagePolicyFlags) {
super(context);
- mPackageUpdatePolicy = packageUpdatePolicy;
+ final int updatePolicyMask = PACKAGE_UPDATE_POLICY_NO_REFRESH
+ | PACKAGE_UPDATE_POLICY_REFRESH_LAZY | PACKAGE_UPDATE_POLICY_REFRESH_EAGER;
+ if ((servicePackagePolicyFlags & updatePolicyMask) == 0) {
+ // If the package update policy is not set, add the default flag
+ servicePackagePolicyFlags |= PACKAGE_UPDATE_POLICY_REFRESH_LAZY;
+ }
+ final int restartPolicyMask = PACKAGE_RESTART_POLICY_NO_REFRESH
+ | PACKAGE_RESTART_POLICY_REFRESH_LAZY | PACKAGE_RESTART_POLICY_REFRESH_EAGER;
+ if ((servicePackagePolicyFlags & restartPolicyMask) == 0) {
+ // If the package restart policy is not set, add the default flag
+ servicePackagePolicyFlags |= PACKAGE_RESTART_POLICY_REFRESH_LAZY;
+ }
+ mServicePackagePolicyFlags = servicePackagePolicyFlags;
mServiceNameResolver = serviceNameResolver;
if (mServiceNameResolver != null) {
@@ -612,6 +643,20 @@ public abstract class AbstractMasterSystemService<M extends AbstractMasterSystem
}
/**
+ * Called after the package data that provides the service for the given user is cleared.
+ */
+ protected void onServicePackageDataClearedLocked(@UserIdInt int userId) {
+ if (verbose) Slog.v(mTag, "onServicePackageDataCleared(" + userId + ")");
+ }
+
+ /**
+ * Called after the package that provides the service for the given user is restarted.
+ */
+ protected void onServicePackageRestartedLocked(@UserIdInt int userId) {
+ if (verbose) Slog.v(mTag, "onServicePackageRestarted(" + userId + ")");
+ }
+
+ /**
* Called after the service is removed from the cache.
*/
@SuppressWarnings("unused")
@@ -713,7 +758,7 @@ public abstract class AbstractMasterSystemService<M extends AbstractMasterSystem
final int size = mServicesCache.size();
pw.print(prefix); pw.print("Debug: "); pw.print(realDebug);
pw.print(" Verbose: "); pw.println(realVerbose);
- pw.print("Refresh on package update: "); pw.println(mPackageUpdatePolicy);
+ pw.print("Package policy flags: "); pw.println(mServicePackagePolicyFlags);
if (mUpdatingPackageNames != null) {
pw.print("Packages being updated: "); pw.println(mUpdatingPackageNames);
}
@@ -768,7 +813,12 @@ public abstract class AbstractMasterSystemService<M extends AbstractMasterSystem
}
mUpdatingPackageNames.put(userId, packageName);
onServicePackageUpdatingLocked(userId);
- if (mPackageUpdatePolicy != PACKAGE_UPDATE_POLICY_NO_REFRESH) {
+ if ((mServicePackagePolicyFlags & PACKAGE_UPDATE_POLICY_NO_REFRESH) != 0) {
+ if (debug) {
+ Slog.d(mTag, "Holding service for user " + userId + " while package "
+ + activePackageName + " is being updated");
+ }
+ } else {
if (debug) {
Slog.d(mTag, "Removing service for user " + userId
+ " because package " + activePackageName
@@ -776,18 +826,14 @@ public abstract class AbstractMasterSystemService<M extends AbstractMasterSystem
}
removeCachedServiceLocked(userId);
- if (mPackageUpdatePolicy == PACKAGE_UPDATE_POLICY_REFRESH_EAGER) {
+ if ((mServicePackagePolicyFlags & PACKAGE_UPDATE_POLICY_REFRESH_EAGER)
+ != 0) {
if (debug) {
Slog.d(mTag, "Eagerly recreating service for user "
+ userId);
}
getServiceForUserLocked(userId);
}
- } else {
- if (debug) {
- Slog.d(mTag, "Holding service for user " + userId + " while package "
- + activePackageName + " is being updated");
- }
}
}
}
@@ -839,7 +885,13 @@ public abstract class AbstractMasterSystemService<M extends AbstractMasterSystem
if (!doit) {
return true;
}
- removeCachedServiceLocked(getChangingUserId());
+ final String action = intent.getAction();
+ final int userId = getChangingUserId();
+ if (Intent.ACTION_PACKAGE_RESTARTED.equals(action)) {
+ handleActiveServiceRestartedLocked(activePackageName, userId);
+ } else {
+ removeCachedServiceLocked(userId);
+ }
} else {
handlePackageUpdateLocked(pkg);
}
@@ -848,6 +900,23 @@ public abstract class AbstractMasterSystemService<M extends AbstractMasterSystem
return false;
}
+ @Override
+ public void onPackageDataCleared(String packageName, int uid) {
+ if (verbose) Slog.v(mTag, "onPackageDataCleared(): " + packageName);
+ final int userId = getChangingUserId();
+ synchronized (mLock) {
+ final S service = peekServiceForUserLocked(userId);
+ if (service != null) {
+ final ComponentName componentName = service.getServiceComponentName();
+ if (componentName != null) {
+ if (packageName.equals(componentName.getPackageName())) {
+ onServicePackageDataClearedLocked(userId);
+ }
+ }
+ }
+ }
+ }
+
private void handleActiveServiceRemoved(@UserIdInt int userId) {
synchronized (mLock) {
removeCachedServiceLocked(userId);
@@ -859,6 +928,31 @@ public abstract class AbstractMasterSystemService<M extends AbstractMasterSystem
}
}
+ private void handleActiveServiceRestartedLocked(String activePackageName,
+ @UserIdInt int userId) {
+ if ((mServicePackagePolicyFlags & PACKAGE_RESTART_POLICY_NO_REFRESH) != 0) {
+ if (debug) {
+ Slog.d(mTag, "Holding service for user " + userId + " while package "
+ + activePackageName + " is being restarted");
+ }
+ } else {
+ if (debug) {
+ Slog.d(mTag, "Removing service for user " + userId
+ + " because package " + activePackageName
+ + " is being restarted");
+ }
+ removeCachedServiceLocked(userId);
+
+ if ((mServicePackagePolicyFlags & PACKAGE_RESTART_POLICY_REFRESH_EAGER) != 0) {
+ if (debug) {
+ Slog.d(mTag, "Eagerly recreating service for user " + userId);
+ }
+ getServiceForUserLocked(userId);
+ }
+ }
+ onServicePackageRestartedLocked(userId);
+ }
+
private String getActiveServicePackageNameLocked() {
final int userId = getChangingUserId();
final S service = peekServiceForUserLocked(userId);
diff --git a/services/core/java/com/android/server/pm/BackgroundDexOptService.java b/services/core/java/com/android/server/pm/BackgroundDexOptService.java
index c7124314cae0..08e55d3b766b 100644
--- a/services/core/java/com/android/server/pm/BackgroundDexOptService.java
+++ b/services/core/java/com/android/server/pm/BackgroundDexOptService.java
@@ -34,6 +34,8 @@ import android.os.ServiceManager;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.storage.StorageManager;
+import android.provider.DeviceConfig;
+import android.text.TextUtils;
import android.util.ArraySet;
import android.util.Log;
import android.util.StatsLog;
@@ -84,6 +86,12 @@ public class BackgroundDexOptService extends JobService {
// Used for calculating space threshold for downgrading unused apps.
private static final int LOW_THRESHOLD_MULTIPLIER_FOR_DOWNGRADE = 2;
+ private static final int DEFAULT_INACTIVE_APP_THRESHOLD_DAYS = 10;
+
+ private static final String DOWNGRADE_UNUSED_APPS_ENABLED = "downgrade_unused_apps_enabled";
+ private static final String INACTIVE_APP_THRESHOLD_DAYS = "inactive_app_threshold_days";
+ private static final String LOW_STORAGE_MULTIPLIER_FOR_DOWNGRADE =
+ "low_storage_threshold_multiplier_for_downgrade";
/**
* Set of failed packages remembered across job runs.
@@ -103,8 +111,6 @@ public class BackgroundDexOptService extends JobService {
private final AtomicBoolean mExitPostBootUpdate = new AtomicBoolean(false);
private final File mDataDir = Environment.getDataDirectory();
- private static final long mDowngradeUnusedAppsThresholdInMillis =
- getDowngradeUnusedAppsThresholdInMillis();
public static void schedule(Context context) {
if (isBackgroundDexoptDisabled()) {
@@ -346,14 +352,14 @@ public class BackgroundDexOptService extends JobService {
// Only downgrade apps when space is low on device.
// Threshold is selected above the lowStorageThreshold so that we can pro-actively clean
// up disk before user hits the actual lowStorageThreshold.
- final long lowStorageThresholdForDowngrade = LOW_THRESHOLD_MULTIPLIER_FOR_DOWNGRADE
+ final long lowStorageThresholdForDowngrade = getLowThresholdMultiplierForDowngrade()
* lowStorageThreshold;
boolean shouldDowngrade = shouldDowngrade(lowStorageThresholdForDowngrade);
Log.d(TAG, "Should Downgrade " + shouldDowngrade);
if (shouldDowngrade) {
Set<String> unusedPackages =
- pm.getUnusedPackages(mDowngradeUnusedAppsThresholdInMillis);
- Log.d(TAG, "Unsused Packages " + String.join(",", unusedPackages));
+ pm.getUnusedPackages(getDowngradeUnusedAppsThresholdInMillis());
+ Log.d(TAG, "Unused Packages " + String.join(",", unusedPackages));
if (!unusedPackages.isEmpty()) {
for (String pkg : unusedPackages) {
@@ -362,12 +368,9 @@ public class BackgroundDexOptService extends JobService {
// Should be aborted by the scheduler.
return abortCode;
}
- if (downgradePackage(pm, pkg, /*isForPrimaryDex*/ true)) {
+ if (downgradePackage(pm, pkg)) {
updatedPackages.add(pkg);
}
- if (supportSecondaryDex) {
- downgradePackage(pm, pkg, /*isForPrimaryDex*/ false);
- }
}
pkgs = new ArraySet<>(pkgs);
@@ -415,39 +418,45 @@ public class BackgroundDexOptService extends JobService {
* Try to downgrade the package to a smaller compilation filter.
* eg. if the package is in speed-profile the package will be downgraded to verify.
* @param pm PackageManagerService
- * @param pkg The package to be downgraded.
- * @param isForPrimaryDex. Apps can have several dex file, primary and secondary.
- * @return true if the package was downgraded.
+ * @param pkg The package to be downgraded
+ * @return true if the package was downgraded
*/
- private boolean downgradePackage(PackageManagerService pm, String pkg,
- boolean isForPrimaryDex) {
+ private boolean downgradePackage(PackageManagerService pm, String pkg) {
Log.d(TAG, "Downgrading " + pkg);
- boolean dex_opt_performed = false;
+ boolean downgradedPrimary = false;
int reason = PackageManagerService.REASON_INACTIVE_PACKAGE_DOWNGRADE;
int dexoptFlags = DexoptOptions.DEXOPT_BOOT_COMPLETE
| DexoptOptions.DEXOPT_IDLE_BACKGROUND_JOB
| DexoptOptions.DEXOPT_DOWNGRADE;
+
long package_size_before = getPackageSize(pm, pkg);
+ // An aggressive downgrade deletes the oat files.
+ boolean aggressive = false;
+ // This applies for system apps or if packages location is not a directory, i.e.
+ // monolithic install.
+ if (!pm.canHaveOatDir(pkg)) {
+ // For apps that don't have the oat directory, instead of downgrading,
+ // remove their compiler artifacts from dalvik cache.
+ pm.deleteOatArtifactsOfPackage(pkg);
+ aggressive = true;
+ downgradedPrimary = true;
+ } else {
+ downgradedPrimary = performDexOptPrimary(pm, pkg, reason, dexoptFlags);
- if (isForPrimaryDex) {
- // This applies for system apps or if packages location is not a directory, i.e.
- // monolithic install.
- if (!pm.canHaveOatDir(pkg)) {
- // For apps that don't have the oat directory, instead of downgrading,
- // remove their compiler artifacts from dalvik cache.
- pm.deleteOatArtifactsOfPackage(pkg);
- } else {
- dex_opt_performed = performDexOptPrimary(pm, pkg, reason, dexoptFlags);
+ if (supportSecondaryDex()) {
+ performDexOptSecondary(pm, pkg, reason, dexoptFlags);
}
- } else {
- dex_opt_performed = performDexOptSecondary(pm, pkg, reason, dexoptFlags);
}
- if (dex_opt_performed) {
+ // This metric aims to log the storage savings when downgrading.
+ // The way disk size is measured using getPackageSize only looks at the primary apks.
+ // Any logs that are due to secondary dex files will show 0% size reduction and pollute
+ // the metrics.
+ if (downgradedPrimary) {
StatsLog.write(StatsLog.APP_DOWNGRADED, pkg, package_size_before,
- getPackageSize(pm, pkg), /*aggressive=*/ false);
+ getPackageSize(pm, pkg), aggressive);
}
- return dex_opt_performed;
+ return downgradedPrimary;
}
private boolean supportSecondaryDex() {
@@ -471,7 +480,7 @@ public class BackgroundDexOptService extends JobService {
* concurrent jobs because PackageDexOptimizer.performDexOpt is synchronized.
* @param pm An instance of PackageManagerService
* @param pkg The package to be downgraded.
- * @param isForPrimaryDex. Apps can have several dex file, primary and secondary.
+ * @param isForPrimaryDex Apps can have several dex file, primary and secondary.
* @return true if the package was downgraded.
*/
private boolean optimizePackage(PackageManagerService pm, String pkg,
@@ -588,12 +597,6 @@ public class BackgroundDexOptService extends JobService {
// the checks above. This check is not "live" - the value is determined by a background
// restart with a period of ~1 minute.
PackageManagerService pm = (PackageManagerService)ServiceManager.getService("package");
- if (pm.isStorageLow()) {
- if (DEBUG_DEXOPT) {
- Log.i(TAG, "Low storage, skipping this run");
- }
- return false;
- }
final ArraySet<String> pkgs = pm.getOptimizablePackages();
if (pkgs.isEmpty()) {
@@ -643,17 +646,77 @@ public class BackgroundDexOptService extends JobService {
}
private static long getDowngradeUnusedAppsThresholdInMillis() {
+ long defaultValue = Long.MAX_VALUE;
+ if (isDowngradeFeatureEnabled()) {
+ return getInactiveAppsThresholdMillis();
+ }
final String sysPropKey = "pm.dexopt.downgrade_after_inactive_days";
String sysPropValue = SystemProperties.get(sysPropKey);
if (sysPropValue == null || sysPropValue.isEmpty()) {
Log.w(TAG, "SysProp " + sysPropKey + " not set");
- return Long.MAX_VALUE;
+ return defaultValue;
+ }
+ try {
+ return TimeUnit.DAYS.toMillis(Long.parseLong(sysPropValue));
+ } catch (NumberFormatException e) {
+ Log.w(TAG, "Couldn't parse long for pm.dexopt.downgrade_after_inactive_days: "
+ + sysPropValue + ". Returning default value instead.");
+ return defaultValue;
}
- return TimeUnit.DAYS.toMillis(Long.parseLong(sysPropValue));
}
private static boolean isBackgroundDexoptDisabled() {
return SystemProperties.getBoolean("pm.dexopt.disable_bg_dexopt" /* key */,
false /* default */);
}
+
+ private static boolean isDowngradeFeatureEnabled() {
+ // DeviceConfig enables the control of on device features via remotely configurable flags,
+ // compared to SystemProperties which is only a way of sharing info system-widely, but are
+ // not configurable on the server-side.
+ String downgradeUnusedAppsEnabledFlag =
+ DeviceConfig.getProperty(
+ DeviceConfig.NAMESPACE_PACKAGE_MANAGER_SERVICE,
+ DOWNGRADE_UNUSED_APPS_ENABLED);
+ return !TextUtils.isEmpty(downgradeUnusedAppsEnabledFlag)
+ && Boolean.parseBoolean(downgradeUnusedAppsEnabledFlag);
+ }
+
+ private static long getInactiveAppsThresholdMillis() {
+ long defaultValue = TimeUnit.DAYS.toMillis(DEFAULT_INACTIVE_APP_THRESHOLD_DAYS);
+ String inactiveAppThresholdDaysFlag =
+ DeviceConfig.getProperty(DeviceConfig.NAMESPACE_PACKAGE_MANAGER_SERVICE,
+ INACTIVE_APP_THRESHOLD_DAYS);
+ if (!TextUtils.isEmpty(inactiveAppThresholdDaysFlag)) {
+ try {
+ return TimeUnit.DAYS.toMillis(Long.parseLong(inactiveAppThresholdDaysFlag));
+ } catch (NumberFormatException e) {
+ Log.w(TAG, "Couldn't parse long for " + INACTIVE_APP_THRESHOLD_DAYS + " flag: "
+ + inactiveAppThresholdDaysFlag + ". Returning default value instead.");
+ return defaultValue;
+ }
+ }
+ return defaultValue;
+ }
+
+ private static int getLowThresholdMultiplierForDowngrade() {
+ int defaultValue = LOW_THRESHOLD_MULTIPLIER_FOR_DOWNGRADE;
+ if (isDowngradeFeatureEnabled()) {
+ String lowStorageThresholdMultiplierFlag =
+ DeviceConfig.getProperty(DeviceConfig.NAMESPACE_PACKAGE_MANAGER_SERVICE,
+ LOW_STORAGE_MULTIPLIER_FOR_DOWNGRADE);
+ if (!TextUtils.isEmpty(lowStorageThresholdMultiplierFlag)) {
+ try {
+ return Integer.parseInt(lowStorageThresholdMultiplierFlag);
+ } catch (NumberFormatException e) {
+ Log.w(TAG, "Couldn't parse long for "
+ + LOW_STORAGE_MULTIPLIER_FOR_DOWNGRADE + " flag: "
+ + lowStorageThresholdMultiplierFlag
+ + ". Returning default value instead.");
+ return defaultValue;
+ }
+ }
+ }
+ return defaultValue;
+ }
}
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
index 2cfd28d23954..22929d835f80 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -650,9 +650,9 @@ public class PermissionManagerService extends IPermissionManager.Stub {
private void updatePermissionFlagsInternal(String permName, String packageName, int flagMask,
int flagValues, int callingUid, int userId, boolean overridePolicy,
PermissionCallback callback) {
- if (ApplicationPackageManager.DEBUG_TRACE_GRANTS
+ if (ApplicationPackageManager.DEBUG_TRACE_PERMISSION_UPDATES
&& ApplicationPackageManager.shouldTraceGrant(packageName, permName, userId)) {
- Log.i(TAG, "System is updating flags for "
+ Log.i(TAG, "System is updating flags for " + packageName + " "
+ permName + " for user " + userId + " "
+ DebugUtils.flagsToString(
PackageManager.class, "FLAG_PERMISSION_", flagMask)
@@ -1185,7 +1185,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
boolean overridePolicy, int callingUid, final int userId, PermissionCallback callback) {
if (ApplicationPackageManager.DEBUG_TRACE_GRANTS
&& ApplicationPackageManager.shouldTraceGrant(packageName, permName, userId)) {
- Log.i(TAG, "System is granting "
+ Log.i(TAG, "System is granting " + packageName + " "
+ permName + " for user " + userId + " on behalf of uid " + callingUid
+ " " + mPackageManagerInt.getNameForUid(callingUid),
new RuntimeException());
@@ -1345,9 +1345,9 @@ public class PermissionManagerService extends IPermissionManager.Stub {
// TODO swap permission name and package name
private void revokeRuntimePermissionInternal(String permName, String packageName,
boolean overridePolicy, int callingUid, final int userId, PermissionCallback callback) {
- if (ApplicationPackageManager.DEBUG_TRACE_GRANTS
+ if (ApplicationPackageManager.DEBUG_TRACE_PERMISSION_UPDATES
&& ApplicationPackageManager.shouldTraceGrant(packageName, permName, userId)) {
- Log.i(TAG, "System is revoking "
+ Log.i(TAG, "System is revoking " + packageName + " "
+ permName + " for user " + userId + " on behalf of uid " + callingUid
+ " " + mPackageManagerInt.getNameForUid(callingUid),
new RuntimeException());
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/gestures/TouchExplorerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/gestures/TouchExplorerTest.java
index 274ca368baa1..104aacb5ef79 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/gestures/TouchExplorerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/gestures/TouchExplorerTest.java
@@ -16,15 +16,18 @@
package com.android.server.accessibility.gestures;
+import static com.android.server.accessibility.gestures.TouchState.STATE_CLEAR;
+import static com.android.server.accessibility.gestures.TouchState.STATE_DELEGATING;
+import static com.android.server.accessibility.gestures.TouchState.STATE_DRAGGING;
+import static com.android.server.accessibility.gestures.TouchState.STATE_TOUCH_EXPLORING;
+
import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
import android.content.Context;
import android.graphics.PointF;
import android.os.SystemClock;
import android.testing.DexmakerShareClassLoaderRule;
-import android.util.DebugUtils;
import android.view.InputDevice;
import android.view.MotionEvent;
@@ -46,10 +49,6 @@ import java.util.List;
@RunWith(AndroidJUnit4.class)
public class TouchExplorerTest {
- public static final int STATE_TOUCH_EXPLORING = 0x00000001;
- public static final int STATE_DRAGGING = 0x00000002;
- public static final int STATE_DELEGATING = 0x00000004;
-
private static final int FLAG_1FINGER = 0x8000;
private static final int FLAG_2FINGERS = 0x0100;
private static final int FLAG_3FINGERS = 0x0200;
@@ -112,7 +111,7 @@ public class TouchExplorerTest {
@Test
public void testTwoFingersMove_shouldDelegatingAndInjectActionDownPointerDown() {
- goFromStateIdleTo(STATE_MOVING_2FINGERS);
+ goFromStateClearTo(STATE_MOVING_2FINGERS);
assertState(STATE_DELEGATING);
assertCapturedEvents(
@@ -123,7 +122,7 @@ public class TouchExplorerTest {
@Test
public void testTwoFingersDrag_shouldDraggingAndActionDown() {
- goFromStateIdleTo(STATE_DRAGGING_2FINGERS);
+ goFromStateClearTo(STATE_DRAGGING_2FINGERS);
assertState(STATE_DRAGGING);
assertCapturedEvents(MotionEvent.ACTION_DOWN);
@@ -133,7 +132,7 @@ public class TouchExplorerTest {
@Test
public void testTwoFingersNotDrag_shouldDelegatingAndActionUpDownPointerDown() {
// only from dragging state, and withMoveHistory no dragging
- goFromStateIdleTo(STATE_PINCH_2FINGERS);
+ goFromStateClearTo(STATE_PINCH_2FINGERS);
assertState(STATE_DELEGATING);
assertCapturedEvents(
@@ -146,7 +145,7 @@ public class TouchExplorerTest {
@Test
public void testThreeFingersMove_shouldDelegatingAnd3ActionPointerDown() {
- goFromStateIdleTo(STATE_MOVING_3FINGERS);
+ goFromStateClearTo(STATE_MOVING_3FINGERS);
assertState(STATE_DELEGATING);
assertCapturedEvents(
@@ -165,52 +164,47 @@ public class TouchExplorerTest {
return new PointF(x, y);
}
- private static String stateToString(int state) {
- return DebugUtils.valueToString(TouchExplorerTest.class, "STATE_", state);
- }
-
- private void goFromStateIdleTo(int state) {
+ private void goFromStateClearTo(int state) {
try {
switch (state) {
- case STATE_TOUCH_EXPLORING: {
+ case STATE_CLEAR: {
mTouchExplorer.onDestroy();
}
break;
case STATE_TOUCH_EXPLORING_1FINGER: {
- goFromStateIdleTo(STATE_TOUCH_EXPLORING);
send(downEvent());
}
break;
case STATE_TOUCH_EXPLORING_2FINGER: {
- goFromStateIdleTo(STATE_TOUCH_EXPLORING_1FINGER);
+ goFromStateClearTo(STATE_TOUCH_EXPLORING_1FINGER);
send(pointerDownEvent());
}
break;
case STATE_TOUCH_EXPLORING_3FINGER: {
- goFromStateIdleTo(STATE_TOUCH_EXPLORING_2FINGER);
+ goFromStateClearTo(STATE_TOUCH_EXPLORING_2FINGER);
send(thirdPointerDownEvent());
}
break;
case STATE_MOVING_2FINGERS: {
- goFromStateIdleTo(STATE_TOUCH_EXPLORING_2FINGER);
+ goFromStateClearTo(STATE_TOUCH_EXPLORING_2FINGER);
moveEachPointers(mLastEvent, p(10, 0), p(5, 10));
send(mLastEvent);
}
break;
case STATE_DRAGGING_2FINGERS: {
- goFromStateIdleTo(STATE_TOUCH_EXPLORING_2FINGER);
+ goFromStateClearTo(STATE_TOUCH_EXPLORING_2FINGER);
moveEachPointers(mLastEvent, p(10, 0), p(10, 0));
send(mLastEvent);
}
break;
case STATE_PINCH_2FINGERS: {
- goFromStateIdleTo(STATE_DRAGGING_2FINGERS);
+ goFromStateClearTo(STATE_DRAGGING_2FINGERS);
moveEachPointers(mLastEvent, p(10, 0), p(-10, 1));
send(mLastEvent);
}
break;
case STATE_MOVING_3FINGERS: {
- goFromStateIdleTo(STATE_TOUCH_EXPLORING_3FINGER);
+ goFromStateClearTo(STATE_TOUCH_EXPLORING_3FINGER);
moveEachPointers(mLastEvent, p(1, 0), p(1, 0), p(1, 0));
send(mLastEvent);
}
@@ -219,7 +213,8 @@ public class TouchExplorerTest {
throw new IllegalArgumentException("Illegal state: " + state);
}
} catch (Throwable t) {
- throw new RuntimeException("Failed to go to state " + stateToString(state), t);
+ throw new RuntimeException("Failed to go to state "
+ + TouchState.getStateSymbolicName(state), t);
}
}
@@ -234,9 +229,9 @@ public class TouchExplorerTest {
}
private void assertState(int expect) {
- final String expectState = "STATE_" + stateToString(expect);
- assertTrue(String.format("Expect state: %s, but: %s", expectState, mTouchExplorer),
- mTouchExplorer.toString().contains(expectState));
+ assertEquals(
+ TouchState.getStateSymbolicName(expect),
+ TouchState.getStateSymbolicName(mTouchExplorer.getState().getState()));
}
private void assertCapturedEvents(int... actionsInOrder) {
diff --git a/tests/BackgroundDexOptServiceIntegrationTests/AndroidManifest.xml b/tests/BackgroundDexOptServiceIntegrationTests/AndroidManifest.xml
index aec9f77cf922..7291dc729541 100644
--- a/tests/BackgroundDexOptServiceIntegrationTests/AndroidManifest.xml
+++ b/tests/BackgroundDexOptServiceIntegrationTests/AndroidManifest.xml
@@ -28,6 +28,8 @@
<uses-permission android:name="android.permission.SET_TIME" />
<uses-permission android:name="android.permission.UPDATE_DEVICE_STATS" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
+ <uses-permission android:name="android.permission.WRITE_DEVICE_CONFIG" />
+ <uses-permission android:name="android.permission.READ_DEVICE_CONFIG" />
<application>
<uses-library android:name="android.test.runner" />
diff --git a/tests/BackgroundDexOptServiceIntegrationTests/src/com/android/server/pm/BackgroundDexOptServiceIntegrationTests.java b/tests/BackgroundDexOptServiceIntegrationTests/src/com/android/server/pm/BackgroundDexOptServiceIntegrationTests.java
index 7d826f7172da..4cd56c3c42be 100644
--- a/tests/BackgroundDexOptServiceIntegrationTests/src/com/android/server/pm/BackgroundDexOptServiceIntegrationTests.java
+++ b/tests/BackgroundDexOptServiceIntegrationTests/src/com/android/server/pm/BackgroundDexOptServiceIntegrationTests.java
@@ -22,6 +22,7 @@ import android.os.Environment;
import android.os.ParcelFileDescriptor;
import android.os.SystemProperties;
import android.os.storage.StorageManager;
+import android.provider.DeviceConfig;
import android.util.Log;
import androidx.test.InstrumentationRegistry;
@@ -30,7 +31,9 @@ import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.BeforeClass;
+import org.junit.Rule;
import org.junit.Test;
+import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
@@ -52,6 +55,13 @@ import java.util.concurrent.TimeUnit;
* 3. Under low storage conditions and package is recently used, check
* that dexopt upgrades test app to $(getprop pm.dexopt.bg-dexopt).
*
+ * When downgrade feature is on (downgrade_unused_apps_enabled flag is set to true):
+ * 4 On low storage, check that the inactive packages are downgraded.
+ * 5. On low storage, check that used packages are upgraded.
+ * 6. On storage completely full, dexopt fails.
+ * 7. Not on low storage, unused packages are upgraded.
+ * 8. Low storage, unused app is downgraded. When app is used again, app is upgraded.
+ *
* Each test case runs "cmd package bg-dexopt-job com.android.frameworks.bgdexopttest".
*
* The setup for these tests make sure this package has been configured to have been recently used
@@ -59,6 +69,10 @@ import java.util.concurrent.TimeUnit;
* recently used, it sets the time forward more than
* `getprop pm.dexopt.downgrade_after_inactive_days` days.
*
+ * For some of the tests, the DeviceConfig flags inactive_app_threshold_days and
+ * downgrade_unused_apps_enabled are set. These turn on/off the downgrade unused apps feature for
+ * all devices and set the time threshold for unused apps.
+ *
* For tests that require low storage, the phone is filled up.
*
* Run with "atest BackgroundDexOptServiceIntegrationTests".
@@ -80,10 +94,14 @@ public final class BackgroundDexOptServiceIntegrationTests {
"pm.dexopt.downgrade_after_inactive_days", 0);
// Needs to be between 1.0 and 2.0.
private static final double LOW_STORAGE_MULTIPLIER = 1.5;
+ private static final int DOWNGRADE_FEATURE_PKG_INACTIVE_AFTER_DAYS = 15;
// The file used to fill up storage.
private File mBigFile;
+ @Rule
+ public ExpectedException mExpectedException = ExpectedException.none();
+
// Remember start time.
@BeforeClass
public static void setUpAll() {
@@ -196,11 +214,27 @@ public final class BackgroundDexOptServiceIntegrationTests {
logSpaceRemaining();
}
+ private void fillUpStorageCompletely() throws IOException {
+ fillUpStorage((getStorageLowBytes()));
+ }
+
// Fill up storage so that device is in low storage condition.
private void fillUpToLowStorage() throws IOException {
fillUpStorage((long) (getStorageLowBytes() * LOW_STORAGE_MULTIPLIER));
}
+ private void setInactivePackageThreshold(int threshold) {
+ DeviceConfig.setProperty(
+ DeviceConfig.NAMESPACE_PACKAGE_MANAGER_SERVICE,
+ "inactive_app_threshold_days", Integer.toString(threshold), false);
+ }
+
+ private void enableDowngradeFeature(boolean enabled) {
+ DeviceConfig.setProperty(
+ DeviceConfig.NAMESPACE_PACKAGE_MANAGER_SERVICE,
+ "downgrade_unused_apps_enabled", Boolean.toString(enabled), false);
+ }
+
// TODO(aeubanks): figure out how to get scheduled bg-dexopt to run
private static void runBackgroundDexOpt() throws IOException {
String result = runShellCommand("cmd package bg-dexopt-job " + PACKAGE_NAME);
@@ -244,7 +278,7 @@ public final class BackgroundDexOptServiceIntegrationTests {
// Test that background dexopt under normal conditions succeeds.
@Test
- public void testBackgroundDexOpt() throws IOException {
+ public void testBackgroundDexOpt_normalConditions_dexOptSucceeds() throws IOException {
// Set filter to quicken.
compilePackageWithFilter(PACKAGE_NAME, "verify");
Assert.assertEquals("verify", getCompilerFilter(PACKAGE_NAME));
@@ -257,17 +291,16 @@ public final class BackgroundDexOptServiceIntegrationTests {
// Test that background dexopt under low storage conditions upgrades used packages.
@Test
- public void testBackgroundDexOptDowngradeSkipRecentlyUsedPackage() throws IOException {
+ public void testBackgroundDexOpt_lowStorage_usedPkgsUpgraded() throws IOException {
// Should be less than DOWNGRADE_AFTER_DAYS.
long deltaDays = DOWNGRADE_AFTER_DAYS - 1;
try {
+ enableDowngradeFeature(false);
// Set time to future.
setTimeFutureDays(deltaDays);
-
// Set filter to quicken.
compilePackageWithFilter(PACKAGE_NAME, "quicken");
Assert.assertEquals("quicken", getCompilerFilter(PACKAGE_NAME));
-
// Fill up storage to trigger low storage threshold.
fillUpToLowStorage();
@@ -282,18 +315,48 @@ public final class BackgroundDexOptServiceIntegrationTests {
}
// Test that background dexopt under low storage conditions downgrades unused packages.
+ // This happens if the system property pm.dexopt.downgrade_after_inactive_days is set
+ // (e.g. on Android Go devices).
@Test
- public void testBackgroundDexOptDowngradeSuccessful() throws IOException {
+ public void testBackgroundDexOpt_lowStorage_unusedPkgsDowngraded()
+ throws IOException {
// Should be more than DOWNGRADE_AFTER_DAYS.
long deltaDays = DOWNGRADE_AFTER_DAYS + 1;
try {
+ enableDowngradeFeature(false);
// Set time to future.
setTimeFutureDays(deltaDays);
-
// Set filter to quicken.
compilePackageWithFilter(PACKAGE_NAME, "quicken");
Assert.assertEquals("quicken", getCompilerFilter(PACKAGE_NAME));
+ // Fill up storage to trigger low storage threshold.
+ fillUpToLowStorage();
+
+ runBackgroundDexOpt();
+
+ // Verify that downgrade is successful.
+ Assert.assertEquals(DOWNGRADE_COMPILER_FILTER, getCompilerFilter(PACKAGE_NAME));
+ } finally {
+ // Reset time.
+ setTimeFutureDays(-deltaDays);
+ }
+ }
+ // Test that the background dexopt downgrades inactive packages when the downgrade feature is
+ // enabled.
+ @Test
+ public void testBackgroundDexOpt_downgradeFeatureEnabled_lowStorage_inactivePkgsDowngraded()
+ throws IOException {
+ // Should be more than DOWNGRADE_FEATURE_PKG_INACTIVE_AFTER_DAYS.
+ long deltaDays = DOWNGRADE_FEATURE_PKG_INACTIVE_AFTER_DAYS + 1;
+ try {
+ enableDowngradeFeature(true);
+ setInactivePackageThreshold(DOWNGRADE_FEATURE_PKG_INACTIVE_AFTER_DAYS);
+ // Set time to future.
+ setTimeFutureDays(deltaDays);
+ // Set filter to quicken.
+ compilePackageWithFilter(PACKAGE_NAME, "quicken");
+ Assert.assertEquals("quicken", getCompilerFilter(PACKAGE_NAME));
// Fill up storage to trigger low storage threshold.
fillUpToLowStorage();
@@ -307,4 +370,106 @@ public final class BackgroundDexOptServiceIntegrationTests {
}
}
+ // Test that the background dexopt upgrades used packages when the downgrade feature is enabled.
+ // This test doesn't fill the device storage completely, but to a multiplier of the low storage
+ // threshold and this is why apps can still be optimized.
+ @Test
+ public void testBackgroundDexOpt_downgradeFeatureEnabled_lowStorage_usedPkgsUpgraded()
+ throws IOException {
+ enableDowngradeFeature(true);
+ // Set filter to quicken.
+ compilePackageWithFilter(PACKAGE_NAME, "quicken");
+ Assert.assertEquals("quicken", getCompilerFilter(PACKAGE_NAME));
+ // Fill up storage to trigger low storage threshold.
+ fillUpToLowStorage();
+
+ runBackgroundDexOpt();
+
+ /// Verify that bg-dexopt is successful in upgrading the used packages.
+ Assert.assertEquals(BG_DEXOPT_COMPILER_FILTER, getCompilerFilter(PACKAGE_NAME));
+ }
+
+ // Test that the background dexopt fails and doesn't change the compilation filter of used
+ // packages when the downgrade feature is enabled and the storage is filled up completely.
+ // The bg-dexopt shouldn't optimise nor downgrade these packages.
+ @Test
+ public void testBackgroundDexOpt_downgradeFeatureEnabled_fillUpStorageCompletely_dexOptFails()
+ throws IOException {
+ enableDowngradeFeature(true);
+ String previousCompilerFilter = getCompilerFilter(PACKAGE_NAME);
+
+ // Fill up storage completely, without using a multiplier for the low storage threshold.
+ fillUpStorageCompletely();
+
+ // When the bg dexopt runs with the storage filled up completely, it will fail.
+ mExpectedException.expect(IllegalStateException.class);
+ runBackgroundDexOpt();
+
+ /// Verify that bg-dexopt doesn't change the compilation filter of used apps.
+ Assert.assertEquals(previousCompilerFilter, getCompilerFilter(PACKAGE_NAME));
+ }
+
+ // Test that the background dexopt upgrades the unused packages when the downgrade feature is
+ // on if the device is not low on storage.
+ @Test
+ public void testBackgroundDexOpt_downgradeFeatureEnabled_notLowStorage_unusedPkgsUpgraded()
+ throws IOException {
+ // Should be more than DOWNGRADE_FEATURE_PKG_INACTIVE_AFTER_DAYS.
+ long deltaDays = DOWNGRADE_FEATURE_PKG_INACTIVE_AFTER_DAYS + 1;
+ try {
+ enableDowngradeFeature(true);
+ setInactivePackageThreshold(DOWNGRADE_FEATURE_PKG_INACTIVE_AFTER_DAYS);
+ // Set time to future.
+ setTimeFutureDays(deltaDays);
+ // Set filter to quicken.
+ compilePackageWithFilter(PACKAGE_NAME, "quicken");
+ Assert.assertEquals("quicken", getCompilerFilter(PACKAGE_NAME));
+
+ runBackgroundDexOpt();
+
+ // Verify that bg-dexopt is successful in upgrading the unused packages when the device
+ // is not low on storage.
+ Assert.assertEquals(BG_DEXOPT_COMPILER_FILTER, getCompilerFilter(PACKAGE_NAME));
+ } finally {
+ // Reset time.
+ setTimeFutureDays(-deltaDays);
+ }
+ }
+
+ // Test that when an unused package (which was downgraded) is used again, it's re-optimized when
+ // bg-dexopt runs again.
+ @Test
+ public void testBackgroundDexOpt_downgradeFeatureEnabled_downgradedPkgsUpgradedAfterUse()
+ throws IOException {
+ // Should be more than DOWNGRADE_FEATURE_PKG_INACTIVE_AFTER_DAYS.
+ long deltaDays = DOWNGRADE_FEATURE_PKG_INACTIVE_AFTER_DAYS + 1;
+ try {
+ enableDowngradeFeature(true);
+ setInactivePackageThreshold(DOWNGRADE_FEATURE_PKG_INACTIVE_AFTER_DAYS);
+ // Set time to future.
+ setTimeFutureDays(deltaDays);
+ // Fill up storage to trigger low storage threshold.
+ fillUpToLowStorage();
+ // Set filter to quicken.
+ compilePackageWithFilter(PACKAGE_NAME, "quicken");
+ Assert.assertEquals("quicken", getCompilerFilter(PACKAGE_NAME));
+
+ runBackgroundDexOpt();
+
+ // Verify that downgrade is successful.
+ Assert.assertEquals(DOWNGRADE_COMPILER_FILTER, getCompilerFilter(PACKAGE_NAME));
+
+ // Reset time.
+ setTimeFutureDays(-deltaDays);
+ deltaDays = 0;
+ runBackgroundDexOpt();
+
+ // Verify that bg-dexopt is successful in upgrading the unused packages that were used
+ // again.
+ Assert.assertEquals(BG_DEXOPT_COMPILER_FILTER, getCompilerFilter(PACKAGE_NAME));
+ } finally {
+ // Reset time.
+ setTimeFutureDays(-deltaDays);
+ }
+ }
}