Make CarPackageManager listen to UX restrictions.
CarPackageManager used to subscribe to CarSensorManager's DRIVING_STATUS
to enforce activity blocking. Changing that to listen to the new
CarUxRestrictionsManagerService.
Add the Home App to the white list.
No change to the current restriction behavior yet, only changing the
source to the new Restriction Manager.
Bug: b/72570830
Test: Compile and boot. CarPackageManager can receive Ux Restriction
events.
Change-Id: I3b96a004cafa2813b7d1855e68cea53c9ffb5f40
diff --git a/service/src/com/android/car/CarUxRestrictionsManagerService.java b/service/src/com/android/car/CarUxRestrictionsManagerService.java
index d9ceedc..f349080 100644
--- a/service/src/com/android/car/CarUxRestrictionsManagerService.java
+++ b/service/src/com/android/car/CarUxRestrictionsManagerService.java
@@ -51,8 +51,11 @@
public CarUxRestrictionsManagerService(Context context, CarDrivingStateService drvService) {
mContext = context;
mDrivingStateService = drvService;
+ // Unrestricted until driving state information is received. During boot up, if driving
+ // state information is not available due to the unavailability of data from VHAL, default
+ // mode is unrestricted.
mCurrentUxRestrictions = createUxRestrictionsEvent(
- CarUxRestrictions.UX_RESTRICTIONS_FULLY_RESTRICTED);
+ CarUxRestrictions.UX_RESTRICTIONS_UNRESTRICTED);
}
@Override
@@ -68,9 +71,6 @@
client.listenerBinder.unlinkToDeath(client, 0);
}
mUxRClients.clear();
- // Fully restricted by default
- mCurrentUxRestrictions = createUxRestrictionsEvent(
- CarUxRestrictions.UX_RESTRICTIONS_FULLY_RESTRICTED);
mDrivingStateService.unregisterDrivingStateChangeListener(
mICarDrivingStateChangeEventListener);
}
diff --git a/service/src/com/android/car/ICarImpl.java b/service/src/com/android/car/ICarImpl.java
index f93ea7f..cd2f47d 100644
--- a/service/src/com/android/car/ICarImpl.java
+++ b/service/src/com/android/car/ICarImpl.java
@@ -109,7 +109,8 @@
mCarDrivingStateService = new CarDrivingStateService(serviceContext, mCarSensorService);
mCarUXRestrictionsService = new CarUxRestrictionsManagerService(serviceContext,
mCarDrivingStateService);
- mCarPackageManagerService = new CarPackageManagerService(serviceContext, mCarSensorService,
+ mCarPackageManagerService = new CarPackageManagerService(serviceContext,
+ mCarUXRestrictionsService,
mSystemActivityMonitoringService);
mCarInputService = new CarInputService(serviceContext, mHal.getInputHal());
mCarProjectionService = new CarProjectionService(serviceContext, mCarInputService);
diff --git a/service/src/com/android/car/pm/ActivityBlockingActivity.java b/service/src/com/android/car/pm/ActivityBlockingActivity.java
index 136fe1a..25446b9 100644
--- a/service/src/com/android/car/pm/ActivityBlockingActivity.java
+++ b/service/src/com/android/car/pm/ActivityBlockingActivity.java
@@ -41,19 +41,13 @@
* via {@link #INTENT_KEY_BLOCKED_ACTIVITY} key. *
*/
public class ActivityBlockingActivity extends Activity {
-
+ private static final boolean DBG = false;
public static final String INTENT_KEY_BLOCKED_ACTIVITY = "blocked_activity";
-
private static final long AUTO_DISMISS_TIME_MS = 3000;
-
private Handler mHandler;
-
private Button mExitButton;
-
private Car mCar;
-
private boolean mExitRequested;
-
private final Runnable mFinishRunnable = () -> handleFinish();
@Override
@@ -103,17 +97,25 @@
}
try {
CarPackageManager carPm = (CarPackageManager) mCar.getCarManager(Car.PACKAGE_SERVICE);
-
// finish itself only when it will not lead into another blocking
if (carPm.isActivityBackedBySafeActivity(getComponentName())) {
+ if (DBG) {
+ Log.d(CarLog.TAG_AM, "New Activity is safe. No more blocking: "
+ + getComponentName().getClassName());
+ }
finish();
return;
}
// back activity is not safe either. Now try home
Intent homeIntent = new Intent(Intent.ACTION_MAIN);
homeIntent.addCategory(Intent.CATEGORY_HOME);
+ // Start a new task before launching the home activity.
+ homeIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
PackageManager pm = getPackageManager();
ComponentName homeComponent = homeIntent.resolveActivity(pm);
+ if (DBG) {
+ Log.d(CarLog.TAG_AM, "Launching home activity: " + homeComponent.getClassName());
+ }
if (carPm.isActivityAllowedWhileDriving(homeComponent.getPackageName(),
homeComponent.getClassName())) {
startActivity(homeIntent);
@@ -124,7 +126,7 @@
+ ", Home Activity:" + homeComponent);
}
} catch (CarNotConnectedException e) {
- Log.w(CarLog.TAG_AM, "Car service not avaiable, will finish", e);
+ Log.w(CarLog.TAG_AM, "Car service not available, will finish", e);
finish();
}
}
diff --git a/service/src/com/android/car/pm/CarPackageManagerService.java b/service/src/com/android/car/pm/CarPackageManagerService.java
index 13ceaa9..ad013b7 100644
--- a/service/src/com/android/car/pm/CarPackageManagerService.java
+++ b/service/src/com/android/car/pm/CarPackageManagerService.java
@@ -15,6 +15,7 @@
*/
package com.android.car.pm;
+import android.annotation.Nullable;
import android.app.ActivityManager.StackInfo;
import android.car.Car;
import android.car.content.pm.AppBlockingPackageInfo;
@@ -22,9 +23,8 @@
import android.car.content.pm.CarAppBlockingPolicyService;
import android.car.content.pm.CarPackageManager;
import android.car.content.pm.ICarPackageManager;
-import android.car.hardware.CarSensorEvent;
-import android.car.hardware.CarSensorManager;
-import android.car.hardware.ICarSensorEventListener;
+import android.car.drivingstate.CarUxRestrictions;
+import android.car.drivingstate.ICarUxRestrictionsChangeListener;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -44,9 +44,9 @@
import android.util.Pair;
import com.android.car.CarLog;
-import com.android.car.CarSensorService;
import com.android.car.CarServiceBase;
import com.android.car.CarServiceUtils;
+import com.android.car.CarUxRestrictionsManagerService;
import com.android.car.R;
import com.android.car.SystemActivityMonitoringService;
import com.android.car.SystemActivityMonitoringService.TopTaskInfoContainer;
@@ -63,13 +63,12 @@
//TODO monitor app installing and refresh policy, bug: 31970400
public class CarPackageManagerService extends ICarPackageManager.Stub implements CarServiceBase {
- static final boolean DBG_POLICY_SET = false;
- static final boolean DBG_POLICY_CHECK = false;
- static final boolean DBG_POLICY_ENFORCEMENT = false;
+ private static final boolean DBG_POLICY_SET = false;
+ private static final boolean DBG_POLICY_CHECK = false;
+ private static final boolean DBG_POLICY_ENFORCEMENT = false;
private final Context mContext;
private final SystemActivityMonitoringService mSystemActivityMonitoringService;
- private final CarSensorService mSensorService;
private final PackageManager mPackageManager;
private final HandlerThread mHandlerThread;
@@ -81,8 +80,7 @@
* Key: packageName of policy service
*/
@GuardedBy("this")
- private final HashMap<String, ClientPolicy> mClientPolicies =
- new HashMap<>();
+ private final HashMap<String, ClientPolicy> mClientPolicies = new HashMap<>();
@GuardedBy("this")
private HashMap<String, AppBlockingPackageInfoWrapper> mSystemWhitelists = new HashMap<>();
@GuardedBy("this")
@@ -91,18 +89,21 @@
@GuardedBy("this")
private final LinkedList<CarAppBlockingPolicy> mWaitingPolicies = new LinkedList<>();
+ private final CarUxRestrictionsManagerService mCarUxRestrictionsService;
private final boolean mEnableActivityBlocking;
private final ComponentName mActivityBlockingActivity;
private final ActivityLaunchListener mActivityLaunchListener = new ActivityLaunchListener();
- private final SensorListener mDrivingStateListener = new SensorListener();
+ private final UxRestrictionsListener mUxRestrictionsListener;
- public CarPackageManagerService(Context context, CarSensorService sensorService,
+ public CarPackageManagerService(Context context,
+ CarUxRestrictionsManagerService uxRestrictionsService,
SystemActivityMonitoringService systemActivityMonitoringService) {
mContext = context;
- mSensorService = sensorService;
+ mCarUxRestrictionsService = uxRestrictionsService;
mSystemActivityMonitoringService = systemActivityMonitoringService;
mPackageManager = mContext.getPackageManager();
+ mUxRestrictionsListener = new UxRestrictionsListener(uxRestrictionsService);
mHandlerThread = new HandlerThread(CarLog.TAG_PACKAGE);
mHandlerThread.start();
mHandler = new PackageHandler(mHandlerThread.getLooper());
@@ -190,7 +191,7 @@
@Override
public boolean isActivityBackedBySafeActivity(ComponentName activityName) {
- if (!mEnableActivityBlocking || !mDrivingStateListener.isRestricted()) {
+ if (!mEnableActivityBlocking || !mUxRestrictionsListener.isRestricted()) {
return true;
}
StackInfo info = mSystemActivityMonitoringService.getFocusedStackForTopActivity(
@@ -291,8 +292,7 @@
}
wakeupClientsWaitingForPolicySetitngLocked();
}
- mSensorService.unregisterSensorListener(CarSensorManager.SENSOR_TYPE_DRIVING_STATUS,
- mDrivingStateListener);
+ mCarUxRestrictionsService.unregisterUxRestrictionsChangeListener(mUxRestrictionsListener);
mSystemActivityMonitoringService.registerActivityLaunchListener(null);
}
@@ -301,14 +301,13 @@
startAppBlockingPolicies();
generateSystemWhitelists();
try {
- mSensorService.registerOrUpdateSensorListener(
- CarSensorManager.SENSOR_TYPE_DRIVING_STATUS, 0, mDrivingStateListener);
+ mCarUxRestrictionsService.registerUxRestrictionsChangeListener(mUxRestrictionsListener);
} catch (IllegalArgumentException e) {
// can happen while mocking is going on while init is still done.
Log.w(CarLog.TAG_PACKAGE, "sensor subscription failed", e);
return;
}
- mDrivingStateListener.resetState();
+ mUxRestrictionsListener.checkIfTopActivityNeedsBlocking();
mSystemActivityMonitoringService.registerActivityLaunchListener(
mActivityLaunchListener);
blockTopActivitiesIfNecessary();
@@ -601,7 +600,7 @@
synchronized (this) {
writer.println("*PackageManagementService*");
writer.println("mEnableActivityBlocking:" + mEnableActivityBlocking);
- writer.println("ActivityRestricted:" + mDrivingStateListener.isRestricted());
+ writer.println("ActivityRestricted:" + mUxRestrictionsListener.isRestricted());
writer.print(dumpPoliciesLocked(true));
}
}
@@ -639,7 +638,7 @@
}
private void blockTopActivityIfNecessary(TopTaskInfoContainer topTask) {
- boolean restricted = mDrivingStateListener.isRestricted();
+ boolean restricted = mUxRestrictionsListener.isRestricted();
if (!restricted) {
return;
}
@@ -647,6 +646,9 @@
}
private void doBlockTopActivityIfNotAllowed(TopTaskInfoContainer topTask) {
+ if (topTask.topActivity == null) {
+ return;
+ }
boolean allowed = isActivityAllowedWhileDriving(
topTask.topActivity.getPackageName(),
topTask.topActivity.getClassName());
@@ -667,7 +669,7 @@
}
private void blockTopActivitiesIfNecessary() {
- boolean restricted = mDrivingStateListener.isRestricted();
+ boolean restricted = mUxRestrictionsListener.isRestricted();
if (!restricted) {
return;
}
@@ -829,37 +831,62 @@
}
}
- private class SensorListener extends ICarSensorEventListener.Stub {
- private int mLatestDrivingState;
+ /**
+ * Listens to the UX restrictions from {@link CarUxRestrictionsManagerService} and initiates
+ * checking if the foreground Activity should be blocked.
+ */
+ private class UxRestrictionsListener extends ICarUxRestrictionsChangeListener.Stub {
+ @GuardedBy("this")
+ @Nullable
+ private CarUxRestrictions mCurrentUxRestrictions;
+ private final CarUxRestrictionsManagerService uxRestrictionsService;
- private void resetState() {
- CarSensorEvent lastEvent = mSensorService.getLatestSensorEvent(
- CarSensorManager.SENSOR_TYPE_DRIVING_STATUS);
- boolean shouldBlock = false;
+ public UxRestrictionsListener(CarUxRestrictionsManagerService service) {
+ uxRestrictionsService = service;
+ mCurrentUxRestrictions = uxRestrictionsService.getCurrentUxRestrictions();
+ }
+
+ @Override
+ public void onUxRestrictionsChanged(CarUxRestrictions restrictions) {
+ if (DBG_POLICY_CHECK) {
+ Log.d(CarLog.TAG_PACKAGE, "Received uxr restrictions: "
+ + restrictions.isRequiresDistractionOptimization()
+ + " : " + restrictions.getActiveRestrictions());
+ }
synchronized (this) {
- if (lastEvent == null) {
- // When driving status is not available yet, do not block.
- // This happens during bootup.
- mLatestDrivingState = CarSensorEvent.DRIVE_STATUS_UNRESTRICTED;
- } else {
- mLatestDrivingState = lastEvent.intValues[0];
- }
- if (mLatestDrivingState != CarSensorEvent.DRIVE_STATUS_UNRESTRICTED) {
- shouldBlock = true;
+ mCurrentUxRestrictions = new CarUxRestrictions(restrictions);
+ }
+ checkIfTopActivityNeedsBlocking();
+ }
+
+ private void checkIfTopActivityNeedsBlocking() {
+ boolean shouldCheck = false;
+ synchronized (this) {
+ if (mCurrentUxRestrictions != null
+ && mCurrentUxRestrictions.isRequiresDistractionOptimization()) {
+ shouldCheck = true;
}
}
- if (shouldBlock) {
+ if (DBG_POLICY_CHECK) {
+ Log.d(CarLog.TAG_PACKAGE, "block?: " + shouldCheck);
+ }
+ if (shouldCheck) {
blockTopActivitiesIfNecessary();
}
}
private synchronized boolean isRestricted() {
- return mLatestDrivingState != CarSensorEvent.DRIVE_STATUS_UNRESTRICTED;
- }
-
- @Override
- public void onSensorChanged(List<CarSensorEvent> events) {
- resetState();
+ // if current restrictions is null, try querying the service, once.
+ if (mCurrentUxRestrictions == null) {
+ mCurrentUxRestrictions = uxRestrictionsService.getCurrentUxRestrictions();
+ }
+ if (mCurrentUxRestrictions != null) {
+ return mCurrentUxRestrictions.isRequiresDistractionOptimization();
+ }
+ // If restriction information is still not available (could happen during bootup),
+ // return not restricted. This maintains parity with previous implementation but needs
+ // a revisit as we test more.
+ return false;
}
}
}