blob: e732a5087ce8a950ec4b745a547df74e5d6fe305 [file] [log] [blame]
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Ram Periathiruvadi38388302018-02-22 16:42:49 -080016
Keun-young Park4aeb4bf2015-12-08 18:31:33 -080017package com.android.car.pm;
18
Mayank Garg771c7452021-03-09 13:33:26 -080019import static android.Manifest.permission.QUERY_ALL_PACKAGES;
20
Yao, Yuxing4c3b93c2019-02-20 09:00:01 -080021import android.annotation.NonNull;
Ram Periathiruvadi2da6d0e2018-01-26 18:02:10 -080022import android.annotation.Nullable;
Mayank Gargfde5e662021-01-19 22:21:10 -080023import android.annotation.UserIdInt;
Yao, Yuxing0c6fc732019-05-10 14:58:49 -070024import android.app.ActivityManager;
Louis Chang3bf2f202020-08-18 13:04:28 +080025import android.app.ActivityTaskManager.RootTaskInfo;
Arnaud Berryd1f88ee2020-02-19 13:49:31 -080026import android.app.PendingIntent;
Keun-young Parke54ac272016-02-16 19:02:18 -080027import android.car.Car;
28import android.car.content.pm.AppBlockingPackageInfo;
29import android.car.content.pm.CarAppBlockingPolicy;
30import android.car.content.pm.CarAppBlockingPolicyService;
31import android.car.content.pm.CarPackageManager;
32import android.car.content.pm.ICarPackageManager;
Ram Periathiruvadi2da6d0e2018-01-26 18:02:10 -080033import android.car.drivingstate.CarUxRestrictions;
34import android.car.drivingstate.ICarUxRestrictionsChangeListener;
Keun young Park40fcb0c2021-09-14 18:47:28 -070035import android.car.hardware.power.CarPowerPolicy;
36import android.car.hardware.power.CarPowerPolicyFilter;
37import android.car.hardware.power.ICarPowerPolicyListener;
38import android.car.hardware.power.PowerComponent;
39import android.car.user.CarUserManager;
Ram Periathiruvadi38388302018-02-22 16:42:49 -080040import android.content.BroadcastReceiver;
Keun-young Park4727da32016-05-31 10:00:51 -070041import android.content.ComponentName;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -080042import android.content.Context;
43import android.content.Intent;
Ram Periathiruvadi38388302018-02-22 16:42:49 -080044import android.content.IntentFilter;
45import android.content.pm.ActivityInfo;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -080046import android.content.pm.PackageInfo;
47import android.content.pm.PackageManager;
48import android.content.pm.PackageManager.NameNotFoundException;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -080049import android.content.pm.ResolveInfo;
Pavel Maltsev0d07c762016-11-03 16:40:15 -070050import android.content.pm.ServiceInfo;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -080051import android.content.pm.Signature;
Keun-young Park4727da32016-05-31 10:00:51 -070052import android.content.res.Resources;
Yao, Yuxingd525de12019-05-06 15:11:48 -070053import android.hardware.display.DisplayManager;
Ram Periathiruvadia6e0d9b2018-04-25 20:19:22 -070054import android.os.Binder;
Ram Periathiruvadid937c322018-06-13 12:28:12 -070055import android.os.Build;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -080056import android.os.Handler;
57import android.os.HandlerThread;
Gaurav Bholaafd79ef2021-06-16 13:22:03 +000058import android.os.IBinder;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -080059import android.os.Looper;
60import android.os.Message;
Gaurav Bholaafd79ef2021-06-16 13:22:03 +000061import android.os.ParcelFileDescriptor;
Ram Periathiruvadia6e0d9b2018-04-25 20:19:22 -070062import android.os.Process;
Gaurav Bholaafd79ef2021-06-16 13:22:03 +000063import android.os.RemoteException;
64import android.os.ServiceManager;
Keun young Park40fcb0c2021-09-14 18:47:28 -070065import android.os.ServiceSpecificException;
66import android.os.SystemProperties;
Yao, Yuxing0c6fc732019-05-10 14:58:49 -070067import android.os.UserHandle;
Gaurav Bhola38569c72021-06-30 15:36:20 +000068import android.text.TextUtils;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -080069import android.util.ArraySet;
Felipe Leme176a5fd2021-01-20 15:48:33 -080070import android.util.IndentingPrintWriter;
Bin Tan2536d402021-02-10 15:28:35 -080071import android.util.LocalLog;
Mayank Garg771c7452021-03-09 13:33:26 -080072import android.util.Log;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -080073import android.util.Pair;
Eric Jeong47b1e242020-12-21 13:41:36 -080074import android.util.Slog;
Yao, Yuxingd525de12019-05-06 15:11:48 -070075import android.util.SparseArray;
Yao, Yuxingcfcc59f2019-03-05 16:35:47 -080076import android.view.Display;
Yao, Yuxingd525de12019-05-06 15:11:48 -070077import android.view.DisplayAddress;
Ram Periathiruvadi8ef1a202018-03-16 17:49:21 -070078
Keun young Park40fcb0c2021-09-14 18:47:28 -070079import com.android.car.CarLocalServices;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -080080import com.android.car.CarLog;
81import com.android.car.CarServiceBase;
82import com.android.car.CarServiceUtils;
Ram Periathiruvadi2da6d0e2018-01-26 18:02:10 -080083import com.android.car.CarUxRestrictionsManagerService;
Keun-young Park4727da32016-05-31 10:00:51 -070084import com.android.car.R;
85import com.android.car.SystemActivityMonitoringService;
86import com.android.car.SystemActivityMonitoringService.TopTaskInfoContainer;
Keun young Park40fcb0c2021-09-14 18:47:28 -070087import com.android.car.power.CarPowerManagementService;
88import com.android.car.user.CarUserService;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -080089import com.android.internal.annotations.GuardedBy;
Ram Periathiruvadi8ef1a202018-03-16 17:49:21 -070090import com.android.internal.annotations.VisibleForTesting;
Gaurav Bholaafd79ef2021-06-16 13:22:03 +000091import com.android.server.utils.Slogf;
Ram Periathiruvadi38388302018-02-22 16:42:49 -080092
Jordan Jozwiak12d59e02019-06-20 18:10:21 -070093import com.google.android.collect.Sets;
94
Gaurav Bholaafd79ef2021-06-16 13:22:03 +000095import java.io.BufferedReader;
96import java.io.FileReader;
97import java.io.IOException;
Keun young Parkb241d022020-04-20 20:31:34 -070098import java.lang.ref.WeakReference;
Ram Periathiruvadi38388302018-02-22 16:42:49 -080099import java.util.ArrayList;
Ram Periathiruvadi295954d2018-04-10 18:27:28 -0700100import java.util.Arrays;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800101import java.util.HashMap;
Mayank Gargfde5e662021-01-19 22:21:10 -0800102import java.util.HashSet;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800103import java.util.LinkedList;
104import java.util.List;
Ram Periathiruvadi46a3a3d2018-03-23 16:58:32 -0700105import java.util.Map;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800106import java.util.Map.Entry;
Mayank Garg771c7452021-03-09 13:33:26 -0800107import java.util.Objects;
Keun-young Park4727da32016-05-31 10:00:51 -0700108import java.util.Set;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800109
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800110public class CarPackageManagerService extends ICarPackageManager.Stub implements CarServiceBase {
Mayank Gargbfa66132021-05-05 19:56:20 -0700111
Keun young Park40fcb0c2021-09-14 18:47:28 -0700112 static final boolean DBG = false;
113
Mayank Gargbfa66132021-05-05 19:56:20 -0700114 private static final String TAG = CarLog.tagFor(CarPackageManagerService.class);
115
Ram Periathiruvadi46a3a3d2018-03-23 16:58:32 -0700116 // Delimiters to parse packages and activities in the configuration XML resource.
117 private static final String PACKAGE_DELIMITER = ",";
118 private static final String PACKAGE_ACTIVITY_DELIMITER = "/";
Yao, Yuxingd1d6a372018-05-08 10:37:43 -0700119 private static final int LOG_SIZE = 20;
Gaurav Bholaafd79ef2021-06-16 13:22:03 +0000120 private static final String[] WINDOW_DUMP_ARGUMENTS = new String[]{"windows"};
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800121
Keun young Park40fcb0c2021-09-14 18:47:28 -0700122 private static final String PROPERTY_RO_DRIVING_SAFETY_REGION =
123 "ro.android.car.drivingsafetyregion";
124
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800125 private final Context mContext;
Keun-young Park4727da32016-05-31 10:00:51 -0700126 private final SystemActivityMonitoringService mSystemActivityMonitoringService;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800127 private final PackageManager mPackageManager;
Yao, Yuxing0c6fc732019-05-10 14:58:49 -0700128 private final ActivityManager mActivityManager;
Yao, Yuxingd525de12019-05-06 15:11:48 -0700129 private final DisplayManager mDisplayManager;
Gaurav Bholaafd79ef2021-06-16 13:22:03 +0000130 private final IBinder mWindowManagerBinder;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800131
Keun young Parkb241d022020-04-20 20:31:34 -0700132 private final HandlerThread mHandlerThread = CarServiceUtils.getHandlerThread(
133 getClass().getSimpleName());
134 private final PackageHandler mHandler = new PackageHandler(mHandlerThread.getLooper(), this);
Yan Zhu211b1fe2019-11-06 15:54:19 -0800135 private final Object mLock = new Object();
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800136
Yao, Yuxingd1d6a372018-05-08 10:37:43 -0700137 // For dumpsys logging.
Bin Tan2536d402021-02-10 15:28:35 -0800138 private final LocalLog mBlockedActivityLogs = new LocalLog(LOG_SIZE);
Yao, Yuxingd1d6a372018-05-08 10:37:43 -0700139
Jordan Jozwiak794abcb2020-07-27 08:08:11 -0700140 // Store the allowlist and blocklist strings from the resource file.
141 private String mConfiguredAllowlist;
142 private String mConfiguredSystemAllowlist;
143 private String mConfiguredBlocklist;
Mayank Gargfde5e662021-01-19 22:21:10 -0800144 @GuardedBy("mLock")
145 private Map<String, Set<String>> mConfiguredAllowlistMap;
146 @GuardedBy("mLock")
147 private Map<String, Set<String>> mConfiguredBlocklistMap;
148
Ram Periathiruvadid937c322018-06-13 12:28:12 -0700149 private final List<String> mAllowedAppInstallSources;
150
Gaurav Bhola83173042021-06-21 09:36:20 +0000151 @GuardedBy("mLock")
152 private final SparseArray<ComponentName> mTopActivityWithDialogPerDisplay = new SparseArray<>();
153
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800154 /**
155 * Hold policy set from policy service or client.
156 * Key: packageName of policy service
157 */
Yan Zhu211b1fe2019-11-06 15:54:19 -0800158 @GuardedBy("mLock")
Ram Periathiruvadi2da6d0e2018-01-26 18:02:10 -0800159 private final HashMap<String, ClientPolicy> mClientPolicies = new HashMap<>();
Yan Zhu211b1fe2019-11-06 15:54:19 -0800160 @GuardedBy("mLock")
Jordan Jozwiak794abcb2020-07-27 08:08:11 -0700161 private HashMap<String, AppBlockingPackageInfoWrapper> mActivityAllowlistMap = new HashMap<>();
Yan Zhu211b1fe2019-11-06 15:54:19 -0800162 @GuardedBy("mLock")
Mayank Gargfde5e662021-01-19 22:21:10 -0800163 private HashSet<String> mActivityDenylistPackages = new HashSet<String>();
164
165 @GuardedBy("mLock")
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800166 private LinkedList<AppBlockingPolicyProxy> mProxies;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800167
Yan Zhu211b1fe2019-11-06 15:54:19 -0800168 @GuardedBy("mLock")
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800169 private final LinkedList<CarAppBlockingPolicy> mWaitingPolicies = new LinkedList<>();
170
Keun young Park40fcb0c2021-09-14 18:47:28 -0700171 @GuardedBy("mLock")
172 private String mCurrentDrivingSafetyRegion = CarPackageManager.DRIVING_SAFETY_REGION_ALL;
173 // Package name + '/' + className format
174 @GuardedBy("mLock")
175 private final ArraySet<String> mTempAllowedActivities = new ArraySet<>();
176
Ram Periathiruvadi2da6d0e2018-01-26 18:02:10 -0800177 private final CarUxRestrictionsManagerService mCarUxRestrictionsService;
Keun young Park40fcb0c2021-09-14 18:47:28 -0700178 private final boolean mEnableActivityBlocking;
179
Keun-young Park4727da32016-05-31 10:00:51 -0700180 private final ComponentName mActivityBlockingActivity;
Gaurav Bholaafd79ef2021-06-16 13:22:03 +0000181 private final boolean mPreventTemplatedAppsFromShowingDialog;
182 private final String mTemplateActivityClassName;
Keun-young Park4727da32016-05-31 10:00:51 -0700183
184 private final ActivityLaunchListener mActivityLaunchListener = new ActivityLaunchListener();
Mayank Gargfde5e662021-01-19 22:21:10 -0800185
Yao, Yuxingd525de12019-05-06 15:11:48 -0700186 // K: (logical) display id of a physical display, V: UXR change listener of this display.
187 // For multi-display, monitor UXR change on each display.
188 private final SparseArray<UxRestrictionsListener> mUxRestrictionsListeners =
189 new SparseArray<>();
Pavel Maltsev38da4312019-04-08 10:38:38 -0700190 private final VendorServiceController mVendorServiceController;
Ram Periathiruvadi295954d2018-04-10 18:27:28 -0700191
Jordan Jozwiak794abcb2020-07-27 08:08:11 -0700192 // Information related to when the installed packages should be parsed for building a allow and
193 // block list
Jordan Jozwiak12d59e02019-06-20 18:10:21 -0700194 private final Set<String> mPackageManagerActions = Sets.newArraySet(
Ram Periathiruvadi295954d2018-04-10 18:27:28 -0700195 Intent.ACTION_PACKAGE_ADDED,
196 Intent.ACTION_PACKAGE_CHANGED,
Ram Periathiruvadi295954d2018-04-10 18:27:28 -0700197 Intent.ACTION_PACKAGE_REMOVED,
Jordan Jozwiak12d59e02019-06-20 18:10:21 -0700198 Intent.ACTION_PACKAGE_REPLACED);
Ram Periathiruvadi295954d2018-04-10 18:27:28 -0700199
200 private final PackageParsingEventReceiver mPackageParsingEventReceiver =
201 new PackageParsingEventReceiver();
Keun-young Park4727da32016-05-31 10:00:51 -0700202
Yao, Yuxing14e83b42018-10-29 18:29:56 -0700203 /**
204 * Name of blocked activity.
205 *
206 * @hide
207 */
208 public static final String BLOCKING_INTENT_EXTRA_BLOCKED_ACTIVITY_NAME = "blocked_activity";
209 /**
210 * int task id of the blocked task.
211 *
212 * @hide
213 */
214 public static final String BLOCKING_INTENT_EXTRA_BLOCKED_TASK_ID = "blocked_task_id";
215 /**
216 * Name of root activity of blocked task.
217 *
218 * @hide
219 */
220 public static final String BLOCKING_INTENT_EXTRA_ROOT_ACTIVITY_NAME = "root_activity_name";
221 /**
222 * Boolean indicating whether the root activity is distraction-optimized (DO).
223 * Blocking screen should show a button to restart the task if {@code true}.
224 *
225 * @hide
226 */
227 public static final String BLOCKING_INTENT_EXTRA_IS_ROOT_ACTIVITY_DO = "is_root_activity_do";
228
Yao, Yuxingd525de12019-05-06 15:11:48 -0700229 /**
230 * int display id of the blocked task.
Jordan Jozwiak12d59e02019-06-20 18:10:21 -0700231 *
Yao, Yuxingd525de12019-05-06 15:11:48 -0700232 * @hide
233 */
234 public static final String BLOCKING_INTENT_EXTRA_DISPLAY_ID = "display_id";
235
Keun young Park40fcb0c2021-09-14 18:47:28 -0700236 private final CarUserManager.UserLifecycleListener mUserLifecycleListener =
237 new CarUserManager.UserLifecycleListener() {
238 @Override
239 public void onEvent(CarUserManager.UserLifecycleEvent event) {
240 if (event.getEventType()
241 == CarUserManager.USER_LIFECYCLE_EVENT_TYPE_SWITCHING) {
242 synchronized (mLock) {
243 resetTempAllowedActivitiesLocked();
244 }
245 }
246 }
247 };
248
249 private final ICarPowerPolicyListener mDisplayPowerPolicyListener =
250 new ICarPowerPolicyListener.Stub() {
251 @Override
252 public void onPolicyChanged(CarPowerPolicy policy,
253 CarPowerPolicy accumulatedPolicy) {
254 if (!policy.isComponentEnabled(PowerComponent.DISPLAY)) {
255 synchronized (mLock) {
256 resetTempAllowedActivitiesLocked();
257 }
258 }
259 }
260 };
261
Ram Periathiruvadi2da6d0e2018-01-26 18:02:10 -0800262 public CarPackageManagerService(Context context,
263 CarUxRestrictionsManagerService uxRestrictionsService,
Mayank Gargfde5e662021-01-19 22:21:10 -0800264 SystemActivityMonitoringService systemActivityMonitoringService) {
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800265 mContext = context;
Ram Periathiruvadi2da6d0e2018-01-26 18:02:10 -0800266 mCarUxRestrictionsService = uxRestrictionsService;
Keun-young Park4727da32016-05-31 10:00:51 -0700267 mSystemActivityMonitoringService = systemActivityMonitoringService;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800268 mPackageManager = mContext.getPackageManager();
Yao, Yuxing0c6fc732019-05-10 14:58:49 -0700269 mActivityManager = mContext.getSystemService(ActivityManager.class);
Yao, Yuxingd525de12019-05-06 15:11:48 -0700270 mDisplayManager = mContext.getSystemService(DisplayManager.class);
Gaurav Bholaafd79ef2021-06-16 13:22:03 +0000271 mWindowManagerBinder = ServiceManager.getService(Context.WINDOW_SERVICE);
Keun-young Park4727da32016-05-31 10:00:51 -0700272 Resources res = context.getResources();
273 mEnableActivityBlocking = res.getBoolean(R.bool.enableActivityBlockingForSafety);
274 String blockingActivity = res.getString(R.string.activityBlockingActivity);
275 mActivityBlockingActivity = ComponentName.unflattenFromString(blockingActivity);
Gaurav Bholacb9439b2021-10-06 00:31:20 +0000276 if (mEnableActivityBlocking && mActivityBlockingActivity == null) {
277 Slogf.wtf(TAG, "mActivityBlockingActivity can't be null when enabled");
278 }
Ram Periathiruvadid937c322018-06-13 12:28:12 -0700279 mAllowedAppInstallSources = Arrays.asList(
280 res.getStringArray(R.array.allowedAppInstallSources));
Pavel Maltsev38da4312019-04-08 10:38:38 -0700281 mVendorServiceController = new VendorServiceController(
Anthony Hughfbb67762019-10-15 12:54:54 -0700282 mContext, mHandler.getLooper());
Gaurav Bholaafd79ef2021-06-16 13:22:03 +0000283 mPreventTemplatedAppsFromShowingDialog =
284 res.getBoolean(R.bool.config_preventTemplatedAppsFromShowingDialog);
285 mTemplateActivityClassName = res.getString(R.string.config_template_activity_class_name);
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800286 }
287
Ram Periathiruvadid937c322018-06-13 12:28:12 -0700288
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800289 @Override
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800290 public void setAppBlockingPolicy(String packageName, CarAppBlockingPolicy policy, int flags) {
Mayank Gargbfa66132021-05-05 19:56:20 -0700291 if (Log.isLoggable(TAG, Log.DEBUG)) {
292 Slog.d(TAG, "policy setting from binder call, client:" + packageName);
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800293 }
Keun young Park6c4fd342019-12-13 12:46:04 -0800294 doSetAppBlockingPolicy(packageName, policy, flags);
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800295 }
296
Yao, Yuxingd1d6a372018-05-08 10:37:43 -0700297 /**
298 * Restarts the requested task. If task with {@code taskId} does not exist, do nothing.
299 */
300 @Override
301 public void restartTask(int taskId) {
Keun young Park572023a2020-06-03 17:29:36 -0700302 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.REAL_GET_TASKS)
303 != PackageManager.PERMISSION_GRANTED) {
304 throw new SecurityException(
305 "requires permission " + android.Manifest.permission.REAL_GET_TASKS);
306 }
Yao, Yuxingd1d6a372018-05-08 10:37:43 -0700307 mSystemActivityMonitoringService.restartTask(taskId);
308 }
309
Keun young Park40fcb0c2021-09-14 18:47:28 -0700310 @Override
311 public String getCurrentDrivingSafetyRegion() {
312 assertAppBlockingOrDrivingStatePermission();
313 synchronized (mLock) {
314 return mCurrentDrivingSafetyRegion;
315 }
316 }
317
318 private String getComponentNameString(String packageName, String className) {
319 return packageName + '/' + className;
320 }
321
322 @Override
323 public void controlOneTimeActivityBlockingBypassingAsUser(String packageName,
324 String activityClassName, boolean bypass, @UserIdInt int userId) {
325 assertAppBlockingPermission();
326 if (!callerCanQueryPackage(packageName)) {
327 throw new SecurityException("cannot query other package");
328 }
329 try {
330 // Read this to check the validity of pkg / activity name. Not checking this can allow
331 // bad apps to be allowed later.
332 CarAppMetadataReader.getSupportedDrivingSafetyRegionsForActivityAsUser(mContext,
333 packageName, activityClassName, userId);
334 } catch (NameNotFoundException e) {
335 throw new ServiceSpecificException(CarPackageManager.ERROR_CODE_NO_PACKAGE,
336 e.getMessage());
337 }
338 String componentName = getComponentNameString(packageName, activityClassName);
339 synchronized (mLock) {
340 if (bypass) {
341 mTempAllowedActivities.add(componentName);
342 } else {
343 mTempAllowedActivities.remove(componentName);
344 }
345 }
346 if (!bypass) { // block top activities if bypassing is disabled.
347 blockTopActivitiesIfNecessary();
348 }
349 }
350
351 @GuardedBy("mLock")
352 private void resetTempAllowedActivitiesLocked() {
353 mTempAllowedActivities.clear();
354 }
355
356 @Override
357 public List<String> getSupportedDrivingSafetyRegionsForActivityAsUser(String packageName,
358 String activityClassName, @UserIdInt int userId) {
359 assertAppBlockingOrDrivingStatePermission();
360 if (!callerCanQueryPackage(packageName)) {
361 throw new SecurityException("cannot query other package");
362 }
363 long token = Binder.clearCallingIdentity();
364 try {
365 return CarAppMetadataReader.getSupportedDrivingSafetyRegionsForActivityAsUser(mContext,
366 packageName, activityClassName, userId);
367 } catch (NameNotFoundException e) {
368 throw new ServiceSpecificException(CarPackageManager.ERROR_CODE_NO_PACKAGE,
369 e.getMessage());
370 } finally {
371 Binder.restoreCallingIdentity(token);
372 }
373 }
374
375 private void assertAppBlockingOrDrivingStatePermission() {
376 if (mContext.checkCallingOrSelfPermission(Car.PERMISSION_CONTROL_APP_BLOCKING)
377 != PackageManager.PERMISSION_GRANTED && mContext.checkCallingOrSelfPermission(
378 Car.PERMISSION_CAR_DRIVING_STATE) != PackageManager.PERMISSION_GRANTED) {
379 throw new SecurityException(
380 "requires permission " + Car.PERMISSION_CONTROL_APP_BLOCKING + " or "
381 + Car.PERMISSION_CAR_DRIVING_STATE);
382 }
383 }
384
385 private void assertAppBlockingPermission() {
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800386 if (mContext.checkCallingOrSelfPermission(Car.PERMISSION_CONTROL_APP_BLOCKING)
387 != PackageManager.PERMISSION_GRANTED) {
388 throw new SecurityException(
389 "requires permission " + Car.PERMISSION_CONTROL_APP_BLOCKING);
390 }
Keun young Park40fcb0c2021-09-14 18:47:28 -0700391 }
392
393 private void doSetAppBlockingPolicy(String packageName, CarAppBlockingPolicy policy,
394 int flags) {
395 assertAppBlockingPermission();
Enrico Granata3da3c612017-01-20 15:24:30 -0800396 CarServiceUtils.assertPackageName(mContext, packageName);
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800397 if (policy == null) {
398 throw new IllegalArgumentException("policy cannot be null");
399 }
400 if ((flags & CarPackageManager.FLAG_SET_POLICY_ADD) != 0 &&
401 (flags & CarPackageManager.FLAG_SET_POLICY_REMOVE) != 0) {
402 throw new IllegalArgumentException(
403 "Cannot set both FLAG_SET_POLICY_ADD and FLAG_SET_POLICY_REMOVE flag");
404 }
Keun young Park6c4fd342019-12-13 12:46:04 -0800405 synchronized (mLock) {
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800406 if ((flags & CarPackageManager.FLAG_SET_POLICY_WAIT_FOR_CHANGE) != 0) {
Keun young Park6c4fd342019-12-13 12:46:04 -0800407 mWaitingPolicies.add(policy);
408 }
409 }
410 mHandler.requestUpdatingPolicy(packageName, policy, flags);
411 if ((flags & CarPackageManager.FLAG_SET_POLICY_WAIT_FOR_CHANGE) != 0) {
412 synchronized (mLock) {
413 try {
414 while (mWaitingPolicies.contains(policy)) {
Keun young Parkff3196b2020-01-07 12:44:10 -0800415 mLock.wait();
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800416 }
Keun young Park6c4fd342019-12-13 12:46:04 -0800417 } catch (InterruptedException e) {
418 // Pass it over binder call
419 throw new IllegalStateException(
420 "Interrupted while waiting for policy completion", e);
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800421 }
422 }
423 }
424 }
425
426 @Override
Ram Periathiruvadie154f582018-03-21 21:53:27 -0700427 public boolean isActivityDistractionOptimized(String packageName, String className) {
Mayank Garg892160e2021-03-22 22:43:23 -0700428 if (!callerCanQueryPackage(packageName)) return false;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800429 assertPackageAndClassName(packageName, className);
Yan Zhu211b1fe2019-11-06 15:54:19 -0800430 synchronized (mLock) {
Mayank Gargbfa66132021-05-05 19:56:20 -0700431 if (Log.isLoggable(TAG, Log.DEBUG)) {
432 Slog.d(TAG, "isActivityDistractionOptimized" + dumpPoliciesLocked(false));
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800433 }
Mayank Gargfde5e662021-01-19 22:21:10 -0800434
Keun young Park40fcb0c2021-09-14 18:47:28 -0700435 if (mTempAllowedActivities.contains(getComponentNameString(packageName,
436 className))) {
437 return true;
438 }
439
Gaurav Bhola83173042021-06-21 09:36:20 +0000440 for (int i = mTopActivityWithDialogPerDisplay.size() - 1; i >= 0; i--) {
441 ComponentName activityWithDialog = mTopActivityWithDialogPerDisplay.get(
442 mTopActivityWithDialogPerDisplay.keyAt(i));
443 if (activityWithDialog.getClassName().equals(className)
444 && activityWithDialog.getPackageName().equals(packageName)) {
445 return false;
446 }
447 }
448
Mayank Gargfde5e662021-01-19 22:21:10 -0800449 if (searchFromClientPolicyBlocklistsLocked(packageName)) {
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800450 return false;
451 }
Mayank Gargfde5e662021-01-19 22:21:10 -0800452
453 if (isActivityInClientPolicyAllowlistsLocked(packageName, className)) {
454 return true;
455 }
456
457 // Check deny and allow list
458 boolean packageBlocked = mActivityDenylistPackages.contains(packageName);
459 AppBlockingPackageInfoWrapper infoWrapper = mActivityAllowlistMap.get(packageName);
460 if (!packageBlocked && infoWrapper == null) {
461 // Update cache
462 updateActivityAllowlistAndDenylistMap(packageName);
463 packageBlocked = mActivityDenylistPackages.contains(packageName);
464 infoWrapper = mActivityAllowlistMap.get(packageName);
465 }
466
467 if (packageBlocked
468 || !isActivityInMapAndMatching(infoWrapper, packageName, className)) {
469 return false;
470 }
471
472 return true;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800473 }
474 }
475
Mayank Garg771c7452021-03-09 13:33:26 -0800476 @VisibleForTesting
Mayank Garg892160e2021-03-22 22:43:23 -0700477 boolean callerCanQueryPackage(String packageName) {
Mayank Garg771c7452021-03-09 13:33:26 -0800478 int callingUid = Binder.getCallingUid();
479 if (hasPermissionGranted(QUERY_ALL_PACKAGES, callingUid)) {
Mayank Garg892160e2021-03-22 22:43:23 -0700480 return true;
Mayank Garg771c7452021-03-09 13:33:26 -0800481 }
482 String[] packages = mPackageManager.getPackagesForUid(callingUid);
483 if (packages != null && packages.length > 0) {
484 for (int i = 0; i < packages.length; i++) {
485 if (Objects.equals(packageName, packages[i])) {
Mayank Garg892160e2021-03-22 22:43:23 -0700486 return true;
Mayank Garg771c7452021-03-09 13:33:26 -0800487 }
488 }
489 }
490
Mayank Gargbfa66132021-05-05 19:56:20 -0700491 Slog.w(TAG, QUERY_ALL_PACKAGES + " permission is needed to query other packages.");
Mayank Garg892160e2021-03-22 22:43:23 -0700492
493 return false;
Mayank Garg771c7452021-03-09 13:33:26 -0800494 }
495
496 private static boolean hasPermissionGranted(String permission, int uid) {
497 return ActivityManager.checkComponentPermission(permission, uid,
498 /* owningUid= */ Process.INVALID_UID,
499 /* exported= */ true) == PackageManager.PERMISSION_GRANTED;
500 }
501
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800502 @Override
Arnaud Berryd1f88ee2020-02-19 13:49:31 -0800503 public boolean isPendingIntentDistractionOptimized(PendingIntent pendingIntent) {
504 ResolveInfo info = mPackageManager.resolveActivity(
505 pendingIntent.getIntent(), PackageManager.MATCH_DEFAULT_ONLY);
506 if (info == null) return false;
507 ActivityInfo activityInfo = info.activityInfo;
508 return isActivityDistractionOptimized(activityInfo.packageName, activityInfo.name);
509 }
510
511 @Override
Ram Periathiruvadie154f582018-03-21 21:53:27 -0700512 public boolean isServiceDistractionOptimized(String packageName, String className) {
Mayank Garg892160e2021-03-22 22:43:23 -0700513 if (!callerCanQueryPackage(packageName)) return false;
514
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800515 if (packageName == null) {
516 throw new IllegalArgumentException("Package name null");
517 }
Yan Zhu211b1fe2019-11-06 15:54:19 -0800518 synchronized (mLock) {
Mayank Gargbfa66132021-05-05 19:56:20 -0700519 if (Log.isLoggable(TAG, Log.DEBUG)) {
520 Slog.d(TAG, "isServiceDistractionOptimized" + dumpPoliciesLocked(false));
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800521 }
Mayank Gargfde5e662021-01-19 22:21:10 -0800522
523 if (searchFromClientPolicyBlocklistsLocked(packageName)) {
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800524 return false;
525 }
Mayank Gargfde5e662021-01-19 22:21:10 -0800526
527 if (searchFromClientPolicyAllowlistsLocked(packageName)) {
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800528 return true;
529 }
Mayank Gargfde5e662021-01-19 22:21:10 -0800530
531 // Check deny and allow list
532 boolean packageBlocked = mActivityDenylistPackages.contains(packageName);
533 AppBlockingPackageInfoWrapper infoWrapper = mActivityAllowlistMap.get(packageName);
534 if (!packageBlocked && infoWrapper == null) {
535 // Update cache
536 updateActivityAllowlistAndDenylistMap(packageName);
537 packageBlocked = mActivityDenylistPackages.contains(packageName);
538 infoWrapper = mActivityAllowlistMap.get(packageName);
539 }
540
541 if (packageBlocked || infoWrapper == null || infoWrapper.info == null) {
542 return false;
543 }
544
545 return true;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800546 }
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800547 }
548
Keun-young Park4727da32016-05-31 10:00:51 -0700549 @Override
550 public boolean isActivityBackedBySafeActivity(ComponentName activityName) {
Mayank Garg771c7452021-03-09 13:33:26 -0800551 if (activityName == null) return false;
Mayank Garg892160e2021-03-22 22:43:23 -0700552 if (!callerCanQueryPackage(activityName.getPackageName())) return false;
553
Louis Chang3bf2f202020-08-18 13:04:28 +0800554 RootTaskInfo info = mSystemActivityMonitoringService.getFocusedStackForTopActivity(
Keun-young Park4727da32016-05-31 10:00:51 -0700555 activityName);
556 if (info == null) { // not top in focused stack
557 return true;
558 }
Yao, Yuxingd525de12019-05-06 15:11:48 -0700559 if (!isUxRestrictedOnDisplay(info.displayId)) {
560 return true;
561 }
Louis Chang3bf2f202020-08-18 13:04:28 +0800562 if (info.childTaskNames.length <= 1) { // nothing below this.
Keun-young Park4727da32016-05-31 10:00:51 -0700563 return false;
564 }
565 ComponentName activityBehind = ComponentName.unflattenFromString(
Louis Chang3bf2f202020-08-18 13:04:28 +0800566 info.childTaskNames[info.childTaskNames.length - 2]);
Ram Periathiruvadie154f582018-03-21 21:53:27 -0700567 return isActivityDistractionOptimized(activityBehind.getPackageName(),
Keun-young Park4727da32016-05-31 10:00:51 -0700568 activityBehind.getClassName());
569 }
570
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800571 public Looper getLooper() {
572 return mHandlerThread.getLooper();
573 }
574
575 private void assertPackageAndClassName(String packageName, String className) {
576 if (packageName == null) {
577 throw new IllegalArgumentException("Package name null");
578 }
579 if (className == null) {
580 throw new IllegalArgumentException("Class name null");
581 }
582 }
583
Yan Zhu211b1fe2019-11-06 15:54:19 -0800584 @GuardedBy("mLock")
Mayank Gargfde5e662021-01-19 22:21:10 -0800585 private boolean searchFromClientPolicyBlocklistsLocked(String packageName) {
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800586 for (ClientPolicy policy : mClientPolicies.values()) {
Jordan Jozwiak794abcb2020-07-27 08:08:11 -0700587 AppBlockingPackageInfoWrapper wrapper = policy.mBlocklistsMap.get(packageName);
Mayank Gargfde5e662021-01-19 22:21:10 -0800588 if (wrapper != null && wrapper.isMatching && wrapper.info != null) {
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800589 return true;
590 }
591 }
Mayank Gargfde5e662021-01-19 22:21:10 -0800592
593 return false;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800594 }
595
Mayank Gargfde5e662021-01-19 22:21:10 -0800596 @GuardedBy("mLock")
597 private boolean searchFromClientPolicyAllowlistsLocked(String packageName) {
598 for (ClientPolicy policy : mClientPolicies.values()) {
599 AppBlockingPackageInfoWrapper wrapper = policy.mAllowlistsMap.get(packageName);
600 if (wrapper != null && wrapper.isMatching && wrapper.info != null) {
601 return true;
602 }
603 }
604 return false;
605 }
606
607 @GuardedBy("mLock")
608 private boolean isActivityInClientPolicyAllowlistsLocked(String packageName, String className) {
609 for (ClientPolicy policy : mClientPolicies.values()) {
610 if (isActivityInMapAndMatching(policy.mAllowlistsMap.get(packageName), packageName,
611 className)) {
612 return true;
613 }
614 }
615 return false;
616 }
617
618 private boolean isActivityInMapAndMatching(AppBlockingPackageInfoWrapper wrapper,
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800619 String packageName, String className) {
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800620 if (wrapper == null || !wrapper.isMatching) {
Mayank Gargbfa66132021-05-05 19:56:20 -0700621 if (Log.isLoggable(TAG, Log.DEBUG)) {
622 Slog.d(TAG, "Pkg not in allowlist:" + packageName);
Ram Periathiruvadi38388302018-02-22 16:42:49 -0800623 }
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800624 return false;
625 }
626 return wrapper.info.isActivityCovered(className);
627 }
628
629 @Override
630 public void init() {
Keun young Park40fcb0c2021-09-14 18:47:28 -0700631 String safetyRegion = SystemProperties.get(PROPERTY_RO_DRIVING_SAFETY_REGION, "");
Yan Zhu211b1fe2019-11-06 15:54:19 -0800632 synchronized (mLock) {
Keun young Park40fcb0c2021-09-14 18:47:28 -0700633 setDrivingSafetyRegionWithCheckLocked(safetyRegion);
Keun-young Park98960812016-10-04 12:50:54 -0700634 mHandler.requestInit();
Keun-young Park4727da32016-05-31 10:00:51 -0700635 }
Keun young Park40fcb0c2021-09-14 18:47:28 -0700636 CarLocalServices.getService(CarUserService.class).addUserLifecycleListener(
637 mUserLifecycleListener);
638 CarLocalServices.getService(CarPowerManagementService.class).addPowerPolicyListener(
639 new CarPowerPolicyFilter.Builder().setComponents(PowerComponent.DISPLAY).build(),
640 mDisplayPowerPolicyListener);
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800641 }
642
643 @Override
644 public void release() {
Keun young Park40fcb0c2021-09-14 18:47:28 -0700645 CarLocalServices.getService(CarPowerManagementService.class).removePowerPolicyListener(
646 mDisplayPowerPolicyListener);
647 CarLocalServices.getService(CarUserService.class).removeUserLifecycleListener(
648 mUserLifecycleListener);
Yan Zhu211b1fe2019-11-06 15:54:19 -0800649 synchronized (mLock) {
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800650 mHandler.requestRelease();
Keun-young Park6dcc50b2016-10-10 19:01:11 -0700651 // wait for release do be done. This guarantees that init is done.
652 try {
Yan Zhu211b1fe2019-11-06 15:54:19 -0800653 mLock.wait();
Keun-young Park6dcc50b2016-10-10 19:01:11 -0700654 } catch (InterruptedException e) {
Mayank Gargbfa66132021-05-05 19:56:20 -0700655 Slog.e(TAG, "Interrupted wait during release");
Yan Zhu211b1fe2019-11-06 15:54:19 -0800656 Thread.currentThread().interrupt();
Keun-young Park6dcc50b2016-10-10 19:01:11 -0700657 }
Jordan Jozwiak794abcb2020-07-27 08:08:11 -0700658 mActivityAllowlistMap.clear();
Mayank Gargfde5e662021-01-19 22:21:10 -0800659 mActivityDenylistPackages.clear();
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800660 mClientPolicies.clear();
661 if (mProxies != null) {
662 for (AppBlockingPolicyProxy proxy : mProxies) {
663 proxy.disconnect();
664 }
665 mProxies.clear();
666 }
Keun young Park6c4fd342019-12-13 12:46:04 -0800667 mWaitingPolicies.clear();
Keun young Park40fcb0c2021-09-14 18:47:28 -0700668 resetTempAllowedActivitiesLocked();
Keun young Parkff3196b2020-01-07 12:44:10 -0800669 mLock.notifyAll();
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800670 }
Ram Periathiruvadi295954d2018-04-10 18:27:28 -0700671 mContext.unregisterReceiver(mPackageParsingEventReceiver);
Keun-young Park98960812016-10-04 12:50:54 -0700672 mSystemActivityMonitoringService.registerActivityLaunchListener(null);
Yao, Yuxingd525de12019-05-06 15:11:48 -0700673 for (int i = 0; i < mUxRestrictionsListeners.size(); i++) {
674 UxRestrictionsListener listener = mUxRestrictionsListeners.valueAt(i);
675 mCarUxRestrictionsService.unregisterUxRestrictionsChangeListener(listener);
676 }
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800677 }
678
Keun young Park40fcb0c2021-09-14 18:47:28 -0700679 @GuardedBy("mLock")
680 private void setDrivingSafetyRegionWithCheckLocked(String region) {
681 if (region.isEmpty()) {
682 mCurrentDrivingSafetyRegion = CarPackageManager.DRIVING_SAFETY_REGION_ALL;
683 } else {
684 mCurrentDrivingSafetyRegion = region;
685 }
686 }
687
688 /**
689 * Reset driving stat and all dynamically added allow list so that region information for
690 * all packages are reset. This also resets one time allow list.
691 */
692 public void resetDrivingSafetyRegion(@NonNull String region) {
693 synchronized (mLock) {
694 setDrivingSafetyRegionWithCheckLocked(region);
695 resetTempAllowedActivitiesLocked();
696 mActivityAllowlistMap.clear();
697 mActivityDenylistPackages.clear();
698 }
699 }
700
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800701 // run from HandlerThread
702 private void doHandleInit() {
Ram Periathiruvadi295954d2018-04-10 18:27:28 -0700703 startAppBlockingPolicies();
704 IntentFilter pkgParseIntent = new IntentFilter();
Ram Periathiruvadi295954d2018-04-10 18:27:28 -0700705 for (String action : mPackageManagerActions) {
706 pkgParseIntent.addAction(action);
707 }
708 pkgParseIntent.addDataScheme("package");
Yao, Yuxing0c6fc732019-05-10 14:58:49 -0700709 mContext.registerReceiverAsUser(mPackageParsingEventReceiver, UserHandle.ALL,
710 pkgParseIntent, null, null);
Yao, Yuxingd525de12019-05-06 15:11:48 -0700711
712 List<Display> physicalDisplays = getPhysicalDisplays();
713
714 // Assume default display (display 0) is always a physical display.
715 Display defaultDisplay = mDisplayManager.getDisplay(Display.DEFAULT_DISPLAY);
716 if (!physicalDisplays.contains(defaultDisplay)) {
Mayank Gargbfa66132021-05-05 19:56:20 -0700717 if (Log.isLoggable(TAG, Log.INFO)) {
718 Slog.i(TAG, "Adding default display to physical displays.");
Yao, Yuxingd525de12019-05-06 15:11:48 -0700719 }
720 physicalDisplays.add(defaultDisplay);
721 }
722 for (Display physicalDisplay : physicalDisplays) {
723 int displayId = physicalDisplay.getDisplayId();
724 UxRestrictionsListener listener = new UxRestrictionsListener(mCarUxRestrictionsService);
725 mUxRestrictionsListeners.put(displayId, listener);
726 mCarUxRestrictionsService.registerUxRestrictionsChangeListener(listener, displayId);
Keun-young Park6dcc50b2016-10-10 19:01:11 -0700727 }
Pavel Maltsev38da4312019-04-08 10:38:38 -0700728 mVendorServiceController.init();
Mayank Gargfde5e662021-01-19 22:21:10 -0800729 mSystemActivityMonitoringService.registerActivityLaunchListener(mActivityLaunchListener);
Ram Periathiruvadi38388302018-02-22 16:42:49 -0800730 }
731
Mayank Gargfde5e662021-01-19 22:21:10 -0800732 private void doParseInstalledPackage(String packageName) {
733 // Delete the package from allowlist and denylist mapping
Yan Zhu211b1fe2019-11-06 15:54:19 -0800734 synchronized (mLock) {
Mayank Gargfde5e662021-01-19 22:21:10 -0800735 mActivityDenylistPackages.remove(packageName);
736 mActivityAllowlistMap.remove(packageName);
Ram Periathiruvadic57678d2018-04-23 09:18:33 -0700737 }
Mayank Gargfde5e662021-01-19 22:21:10 -0800738
739 // Generate allowlist and denylist mapping for the package
740 updateActivityAllowlistAndDenylistMap(packageName);
Yao, Yuxingd525de12019-05-06 15:11:48 -0700741 blockTopActivitiesIfNecessary();
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800742 }
743
Yan Zhu211b1fe2019-11-06 15:54:19 -0800744 private void doHandleRelease() {
745 synchronized (mLock) {
746 mVendorServiceController.release();
747 mLock.notifyAll();
748 }
Keun-young Park6dcc50b2016-10-10 19:01:11 -0700749 }
750
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800751 private void doUpdatePolicy(String packageName, CarAppBlockingPolicy policy, int flags) {
Mayank Gargbfa66132021-05-05 19:56:20 -0700752 if (Log.isLoggable(TAG, Log.DEBUG)) {
753 Slog.d(TAG, "setting policy from:" + packageName + ",policy:" + policy + ",flags:0x"
754 + Integer.toHexString(flags));
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800755 }
Jordan Jozwiak794abcb2020-07-27 08:08:11 -0700756 AppBlockingPackageInfoWrapper[] blocklistWrapper = verifyList(policy.blacklists);
757 AppBlockingPackageInfoWrapper[] allowlistWrapper = verifyList(policy.whitelists);
Yan Zhu211b1fe2019-11-06 15:54:19 -0800758 synchronized (mLock) {
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800759 ClientPolicy clientPolicy = mClientPolicies.get(packageName);
760 if (clientPolicy == null) {
761 clientPolicy = new ClientPolicy();
762 mClientPolicies.put(packageName, clientPolicy);
763 }
764 if ((flags & CarPackageManager.FLAG_SET_POLICY_ADD) != 0) {
Jordan Jozwiak794abcb2020-07-27 08:08:11 -0700765 clientPolicy.addToBlocklists(blocklistWrapper);
766 clientPolicy.addToAllowlists(allowlistWrapper);
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800767 } else if ((flags & CarPackageManager.FLAG_SET_POLICY_REMOVE) != 0) {
Jordan Jozwiak794abcb2020-07-27 08:08:11 -0700768 clientPolicy.removeBlocklists(blocklistWrapper);
769 clientPolicy.removeAllowlists(allowlistWrapper);
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800770 } else { //replace.
Jordan Jozwiak794abcb2020-07-27 08:08:11 -0700771 clientPolicy.replaceBlocklists(blocklistWrapper);
772 clientPolicy.replaceAllowlists(allowlistWrapper);
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800773 }
774 if ((flags & CarPackageManager.FLAG_SET_POLICY_WAIT_FOR_CHANGE) != 0) {
Keun young Park6c4fd342019-12-13 12:46:04 -0800775 mWaitingPolicies.remove(policy);
Keun young Parkff3196b2020-01-07 12:44:10 -0800776 mLock.notifyAll();
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800777 }
Mayank Gargbfa66132021-05-05 19:56:20 -0700778 if (Log.isLoggable(TAG, Log.DEBUG)) {
779 Slog.d(TAG, "policy set:" + dumpPoliciesLocked(false));
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800780 }
781 }
Keun-young Park4727da32016-05-31 10:00:51 -0700782 blockTopActivitiesIfNecessary();
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800783 }
784
785 private AppBlockingPackageInfoWrapper[] verifyList(AppBlockingPackageInfo[] list) {
786 if (list == null) {
787 return null;
788 }
789 LinkedList<AppBlockingPackageInfoWrapper> wrappers = new LinkedList<>();
790 for (int i = 0; i < list.length; i++) {
791 AppBlockingPackageInfo info = list[i];
792 if (info == null) {
793 continue;
794 }
795 boolean isMatching = isInstalledPackageMatching(info);
796 wrappers.add(new AppBlockingPackageInfoWrapper(info, isMatching));
797 }
798 return wrappers.toArray(new AppBlockingPackageInfoWrapper[wrappers.size()]);
799 }
800
801 boolean isInstalledPackageMatching(AppBlockingPackageInfo info) {
Yao, Yuxing4ddb2c62019-02-04 11:26:46 -0800802 PackageInfo packageInfo;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800803 try {
804 packageInfo = mPackageManager.getPackageInfo(info.packageName,
805 PackageManager.GET_SIGNATURES);
806 } catch (NameNotFoundException e) {
807 return false;
808 }
809 if (packageInfo == null) {
810 return false;
811 }
812 // if it is system app and client specified the flag, do not check signature
813 if ((info.flags & AppBlockingPackageInfo.FLAG_SYSTEM_APP) == 0 ||
814 (!packageInfo.applicationInfo.isSystemApp() &&
815 !packageInfo.applicationInfo.isUpdatedSystemApp())) {
Yao, Yuxing4ddb2c62019-02-04 11:26:46 -0800816 Signature[] signatures = packageInfo.signatures;
817 if (!isAnySignatureMatching(signatures, info.signatures)) {
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800818 return false;
819 }
820 }
821 int version = packageInfo.versionCode;
822 if (info.minRevisionCode == 0) {
823 if (info.maxRevisionCode == 0) { // all versions
824 return true;
825 } else { // only max version matters
826 return info.maxRevisionCode > version;
827 }
828 } else { // min version matters
829 if (info.maxRevisionCode == 0) {
830 return info.minRevisionCode < version;
831 } else {
832 return (info.minRevisionCode < version) && (info.maxRevisionCode > version);
833 }
834 }
835 }
836
837 /**
838 * Any signature from policy matching with package's signatures is treated as matching.
839 */
840 boolean isAnySignatureMatching(Signature[] fromPackage, Signature[] fromPolicy) {
841 if (fromPackage == null) {
842 return false;
843 }
844 if (fromPolicy == null) {
845 return false;
846 }
847 ArraySet<Signature> setFromPackage = new ArraySet<Signature>();
848 for (Signature sig : fromPackage) {
849 setFromPackage.add(sig);
850 }
851 for (Signature sig : fromPolicy) {
852 if (setFromPackage.contains(sig)) {
853 return true;
854 }
855 }
856 return false;
857 }
858
Mayank Gargfde5e662021-01-19 22:21:10 -0800859 private AppBlockingPackageInfoWrapper getPackageInfoWrapperForUser(String packageName,
860 @UserIdInt int userId, Map<String, Set<String>> configAllowlist,
861 Map<String, Set<String>> configBlocklist) {
862 PackageInfo info;
863 try {
864 info = mPackageManager.getPackageInfoAsUser(packageName,
865 PackageManager.GET_SIGNATURES | PackageManager.GET_ACTIVITIES
866 | PackageManager.MATCH_DIRECT_BOOT_AWARE
867 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
868 | PackageManager.MATCH_DISABLED_COMPONENTS,
869 userId);
870 } catch (NameNotFoundException e) {
Mayank Gargbfa66132021-05-05 19:56:20 -0700871 Slog.w(TAG, packageName + " not installed! User Id: " + userId);
Mayank Gargfde5e662021-01-19 22:21:10 -0800872 return null;
873 }
874
875
876 if (info == null || info.applicationInfo == null) {
877 return null;
878 }
879
880 int flags = 0;
881 Set<String> activities = new ArraySet<>();
882
883 if (info.applicationInfo.isSystemApp()
884 || info.applicationInfo.isUpdatedSystemApp()) {
885 flags = AppBlockingPackageInfo.FLAG_SYSTEM_APP;
886 }
887
888 /* 1. Check if all or some of this app is in the <activityAllowlist> or
889 <systemActivityAllowlist> in config.xml */
890 Set<String> configActivitiesForPackage = configAllowlist.get(info.packageName);
891 if (configActivitiesForPackage != null) {
Mayank Gargbfa66132021-05-05 19:56:20 -0700892 if (Log.isLoggable(TAG, Log.DEBUG)) {
893 Slog.d(TAG, info.packageName + " allowlisted");
Mayank Gargfde5e662021-01-19 22:21:10 -0800894 }
Mayank Gargbfa66132021-05-05 19:56:20 -0700895
Mayank Gargfde5e662021-01-19 22:21:10 -0800896 if (configActivitiesForPackage.isEmpty()) {
897 // Whole Pkg has been allowlisted
898 flags |= AppBlockingPackageInfo.FLAG_WHOLE_ACTIVITY;
899 // Add all activities to the allowlist
900 List<String> activitiesForPackage = getActivitiesInPackage(info);
901 if (activitiesForPackage != null) {
902 activities.addAll(activitiesForPackage);
903 } else {
Mayank Gargbfa66132021-05-05 19:56:20 -0700904 if (Log.isLoggable(TAG, Log.DEBUG)) {
905 Slog.d(TAG, info.packageName + ": Activities null");
Mayank Gargfde5e662021-01-19 22:21:10 -0800906 }
907 }
908 } else {
Mayank Gargbfa66132021-05-05 19:56:20 -0700909 if (Log.isLoggable(TAG, Log.DEBUG)) {
910 Slog.d(TAG, "Partially Allowlisted. WL Activities: "
911 + configActivitiesForPackage);
Mayank Gargfde5e662021-01-19 22:21:10 -0800912 }
913 activities.addAll(configActivitiesForPackage);
914 }
915 }
916 /* 2. If app is not listed in the config.xml check their Manifest meta-data to
917 see if they have any Distraction Optimized(DO) activities.
918 For non system apps, we check if the app install source was a permittable
919 source. This prevents side-loaded apps to fake DO. Bypass the check
920 for debug builds for development convenience. */
921 if (!isDebugBuild()
922 && !info.applicationInfo.isSystemApp()
923 && !info.applicationInfo.isUpdatedSystemApp()) {
924 try {
925 if (mAllowedAppInstallSources != null) {
926 String installerName = mPackageManager.getInstallerPackageName(
927 info.packageName);
928 if (installerName == null || (installerName != null
929 && !mAllowedAppInstallSources.contains(installerName))) {
Mayank Gargbfa66132021-05-05 19:56:20 -0700930 Slog.w(TAG,
Mayank Gargfde5e662021-01-19 22:21:10 -0800931 info.packageName + " not installed from permitted sources "
932 + (installerName == null ? "NULL" : installerName));
933 return null;
934 }
935 }
936 } catch (IllegalArgumentException e) {
Mayank Gargbfa66132021-05-05 19:56:20 -0700937 Slog.w(TAG, info.packageName + " not installed!");
Mayank Gargfde5e662021-01-19 22:21:10 -0800938 return null;
939 }
940 }
941
942 try {
Keun young Park40fcb0c2021-09-14 18:47:28 -0700943 String[] doActivities = findDistractionOptimizedActivitiesAsUser(info.packageName,
944 userId);
Mayank Gargfde5e662021-01-19 22:21:10 -0800945 if (doActivities != null) {
946 // Some of the activities in this app are Distraction Optimized.
Mayank Gargbfa66132021-05-05 19:56:20 -0700947 if (Log.isLoggable(TAG, Log.DEBUG)) {
Mayank Gargfde5e662021-01-19 22:21:10 -0800948 for (String activity : doActivities) {
Mayank Gargbfa66132021-05-05 19:56:20 -0700949 Slog.d(TAG, "adding " + activity + " from " + info.packageName
950 + " to allowlist");
Mayank Gargfde5e662021-01-19 22:21:10 -0800951 }
952 }
Mayank Gargbfa66132021-05-05 19:56:20 -0700953
Mayank Gargfde5e662021-01-19 22:21:10 -0800954 activities.addAll(Arrays.asList(doActivities));
955 }
956 } catch (NameNotFoundException e) {
Mayank Gargbfa66132021-05-05 19:56:20 -0700957 Slog.w(TAG, "Error reading metadata: " + info.packageName);
Mayank Gargfde5e662021-01-19 22:21:10 -0800958 return null;
959 }
960
961 // Nothing to add to allowlist
962 if (activities.isEmpty()) {
963 return null;
964 }
965
966 /* 3. Check if parsed activity is in <activityBlocklist> in config.xml. Anything
967 in blocklist should not be allowlisted, either as D.O. or by config. */
968 if (configBlocklist.containsKey(info.packageName)) {
969 Set<String> configBlocklistActivities = configBlocklist.get(info.packageName);
970 if (configBlocklistActivities.isEmpty()) {
971 // Whole package should be blocklisted.
972 return null;
973 }
974 activities.removeAll(configBlocklistActivities);
975 }
976
977 Signature[] signatures;
978 signatures = info.signatures;
979 AppBlockingPackageInfo appBlockingInfo = new AppBlockingPackageInfo(info.packageName,
980 /* minRevisionCode = */ 0, /* maxRevisionCode = */ 0, flags, signatures,
981 activities.toArray(new String[activities.size()]));
982 AppBlockingPackageInfoWrapper wrapper = new AppBlockingPackageInfoWrapper(
983 appBlockingInfo, true);
984 return wrapper;
985 }
986
Keun-young Park4727da32016-05-31 10:00:51 -0700987 /**
Mayank Gargfde5e662021-01-19 22:21:10 -0800988 * Update map of allowlisted packages and activities of the form {pkgName, Allowlisted
989 * activities} and set of denylisted packages. The information can come from a configuration XML
990 * resource or from the apps marking their activities as distraction optimized.
Keun-young Park4727da32016-05-31 10:00:51 -0700991 */
Mayank Gargfde5e662021-01-19 22:21:10 -0800992 private void updateActivityAllowlistAndDenylistMap(String packageName) {
993 int userId = mActivityManager.getCurrentUser();
Mayank Gargbfa66132021-05-05 19:56:20 -0700994 Slog.d(TAG, "Updating allowlist and denylist mapping for package: " + packageName
995 + " for UserId: " + userId);
Jordan Jozwiak794abcb2020-07-27 08:08:11 -0700996 // Get the apps/activities that are allowlisted in the configuration XML resources.
997 Map<String, Set<String>> configAllowlist = generateConfigAllowlist();
998 Map<String, Set<String>> configBlocklist = generateConfigBlocklist();
Yao, Yuxing0c6fc732019-05-10 14:58:49 -0700999
Mayank Gargfde5e662021-01-19 22:21:10 -08001000 AppBlockingPackageInfoWrapper wrapper =
1001 getPackageInfoWrapperForUser(packageName, userId, configAllowlist, configBlocklist);
1002
1003 if (wrapper == null && userId != UserHandle.USER_SYSTEM) {
Mayank Gargbfa66132021-05-05 19:56:20 -07001004 Slog.d(TAG, "Updating allowlist and denylist mapping for package: " + packageName
1005 + " for UserId: " + UserHandle.USER_SYSTEM);
Mayank Gargfde5e662021-01-19 22:21:10 -08001006 // check package for system user, in case package is disabled for current user
1007 wrapper = getPackageInfoWrapperForUser(packageName, UserHandle.USER_SYSTEM,
1008 configAllowlist, configBlocklist);
Yao, Yuxing0c6fc732019-05-10 14:58:49 -07001009 }
Mayank Gargfde5e662021-01-19 22:21:10 -08001010
Yan Zhu211b1fe2019-11-06 15:54:19 -08001011 synchronized (mLock) {
Mayank Gargfde5e662021-01-19 22:21:10 -08001012 if (wrapper != null) {
Keun young Park40fcb0c2021-09-14 18:47:28 -07001013 if (DBG) {
1014 Slog.d(TAG, "Package: " + packageName + " added in allowlist.");
1015 }
Mayank Gargfde5e662021-01-19 22:21:10 -08001016 mActivityAllowlistMap.put(packageName, wrapper);
1017 } else {
Keun young Park40fcb0c2021-09-14 18:47:28 -07001018 if (DBG) {
1019 Slog.d(TAG, "Package: " + packageName + " added in denylist.");
1020 }
Mayank Gargfde5e662021-01-19 22:21:10 -08001021 mActivityDenylistPackages.add(packageName);
1022 }
Yao, Yuxing0c6fc732019-05-10 14:58:49 -07001023 }
1024 }
1025
Jordan Jozwiak794abcb2020-07-27 08:08:11 -07001026 private Map<String, Set<String>> generateConfigAllowlist() {
Mayank Gargfde5e662021-01-19 22:21:10 -08001027 synchronized (mLock) {
1028 if (mConfiguredAllowlistMap != null) return mConfiguredAllowlistMap;
1029
1030 Map<String, Set<String>> configAllowlist = new HashMap<>();
1031 mConfiguredAllowlist = mContext.getString(R.string.activityAllowlist);
1032 if (mConfiguredAllowlist == null) {
Mayank Gargbfa66132021-05-05 19:56:20 -07001033 Slog.w(TAG, "Allowlist is null.");
Ram Periathiruvadie6e2ac32018-05-02 14:57:46 -07001034 }
Mayank Gargfde5e662021-01-19 22:21:10 -08001035 parseConfigList(mConfiguredAllowlist, configAllowlist);
Yao, Yuxing0c6fc732019-05-10 14:58:49 -07001036
Mayank Gargfde5e662021-01-19 22:21:10 -08001037 mConfiguredSystemAllowlist = mContext.getString(R.string.systemActivityAllowlist);
1038 if (mConfiguredSystemAllowlist == null) {
Mayank Gargbfa66132021-05-05 19:56:20 -07001039 Slog.w(TAG, "System allowlist is null.");
Yao, Yuxing4c3b93c2019-02-20 09:00:01 -08001040 }
Mayank Gargfde5e662021-01-19 22:21:10 -08001041 parseConfigList(mConfiguredSystemAllowlist, configAllowlist);
Yao, Yuxing4c3b93c2019-02-20 09:00:01 -08001042
Mayank Gargfde5e662021-01-19 22:21:10 -08001043 // Add the blocking overlay activity to the allowlist, since that needs to run in a
1044 // restricted state to communicate the reason an app was blocked.
1045 Set<String> defaultActivity = new ArraySet<>();
1046 if (mActivityBlockingActivity != null) {
1047 defaultActivity.add(mActivityBlockingActivity.getClassName());
1048 configAllowlist.put(mActivityBlockingActivity.getPackageName(), defaultActivity);
1049 }
Ram Periathiruvadi38388302018-02-22 16:42:49 -08001050
Mayank Gargfde5e662021-01-19 22:21:10 -08001051 mConfiguredAllowlistMap = configAllowlist;
1052 return configAllowlist;
1053 }
Yao, Yuxing0c6fc732019-05-10 14:58:49 -07001054 }
1055
Jordan Jozwiak794abcb2020-07-27 08:08:11 -07001056 private Map<String, Set<String>> generateConfigBlocklist() {
Mayank Gargfde5e662021-01-19 22:21:10 -08001057 synchronized (mLock) {
1058 if (mConfiguredBlocklistMap != null) return mConfiguredBlocklistMap;
Yao, Yuxing0c6fc732019-05-10 14:58:49 -07001059
Mayank Gargfde5e662021-01-19 22:21:10 -08001060 Map<String, Set<String>> configBlocklist = new HashMap<>();
1061 mConfiguredBlocklist = mContext.getString(R.string.activityDenylist);
1062 if (mConfiguredBlocklist == null) {
Mayank Gargbfa66132021-05-05 19:56:20 -07001063 if (Log.isLoggable(TAG, Log.DEBUG)) {
1064 Slog.d(TAG, "Null blocklist in config");
Ram Periathiruvadi38388302018-02-22 16:42:49 -08001065 }
Yao, Yuxing2a1e1d92019-01-08 11:58:52 -08001066 }
Mayank Gargfde5e662021-01-19 22:21:10 -08001067 parseConfigList(mConfiguredBlocklist, configBlocklist);
Yao, Yuxing2a1e1d92019-01-08 11:58:52 -08001068
Mayank Gargfde5e662021-01-19 22:21:10 -08001069 mConfiguredBlocklistMap = configBlocklist;
1070 return configBlocklist;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001071 }
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001072 }
1073
Ram Periathiruvadid937c322018-06-13 12:28:12 -07001074 private boolean isDebugBuild() {
1075 return Build.IS_USERDEBUG || Build.IS_ENG;
1076 }
1077
Ram Periathiruvadi46a3a3d2018-03-23 16:58:32 -07001078 /**
Yao, Yuxing4c3b93c2019-02-20 09:00:01 -08001079 * Parses the given resource and updates the input map of packages and activities.
1080 *
1081 * Key is package name and value is list of activities. Empty set implies whole package is
Ram Periathiruvadi46a3a3d2018-03-23 16:58:32 -07001082 * included.
Yao, Yuxing4c3b93c2019-02-20 09:00:01 -08001083 *
1084 * When there are multiple entries regarding one package, the entry with
Jordan Jozwiak794abcb2020-07-27 08:08:11 -07001085 * greater scope wins. Namely if there were 2 entries such that one allowlists
1086 * an activity, and the other allowlists the entire package of the activity,
1087 * the package is allowlisted, regardless of input order.
Ram Periathiruvadi46a3a3d2018-03-23 16:58:32 -07001088 */
Yao, Yuxing4c3b93c2019-02-20 09:00:01 -08001089 @VisibleForTesting
1090 /* package */ void parseConfigList(String configList,
1091 @NonNull Map<String, Set<String>> packageToActivityMap) {
Ram Periathiruvadie6e2ac32018-05-02 14:57:46 -07001092 if (configList == null) {
Yao, Yuxing4c3b93c2019-02-20 09:00:01 -08001093 return;
Ram Periathiruvadie6e2ac32018-05-02 14:57:46 -07001094 }
Ram Periathiruvadi46a3a3d2018-03-23 16:58:32 -07001095 String[] entries = configList.split(PACKAGE_DELIMITER);
1096 for (String entry : entries) {
1097 String[] packageActivityPair = entry.split(PACKAGE_ACTIVITY_DELIMITER);
1098 Set<String> activities = packageToActivityMap.get(packageActivityPair[0]);
1099 boolean newPackage = false;
1100 if (activities == null) {
1101 activities = new ArraySet<>();
1102 newPackage = true;
1103 packageToActivityMap.put(packageActivityPair[0], activities);
1104 }
1105 if (packageActivityPair.length == 1) { // whole package
1106 activities.clear();
1107 } else if (packageActivityPair.length == 2) {
Jordan Jozwiak794abcb2020-07-27 08:08:11 -07001108 // add class name only when the whole package is not allowlisted.
Ram Periathiruvadi46a3a3d2018-03-23 16:58:32 -07001109 if (newPackage || (activities.size() > 0)) {
1110 activities.add(packageActivityPair[1]);
1111 }
1112 }
1113 }
Ram Periathiruvadi46a3a3d2018-03-23 16:58:32 -07001114 }
1115
Ram Periathiruvadi38388302018-02-22 16:42:49 -08001116 @Nullable
Yao, Yuxing2a1e1d92019-01-08 11:58:52 -08001117 private List<String> getActivitiesInPackage(PackageInfo info) {
Ram Periathiruvadi38388302018-02-22 16:42:49 -08001118 if (info == null || info.activities == null) {
1119 return null;
1120 }
1121 List<String> activityList = new ArrayList<>();
1122 for (ActivityInfo aInfo : info.activities) {
1123 activityList.add(aInfo.name);
1124 }
Yao, Yuxing2a1e1d92019-01-08 11:58:52 -08001125 return activityList;
Ram Periathiruvadi38388302018-02-22 16:42:49 -08001126 }
1127
Ram Periathiruvadi8ef1a202018-03-16 17:49:21 -07001128 /**
1129 * Checks if there are any {@link CarAppBlockingPolicyService} and creates a proxy to
1130 * bind to them and retrieve the {@link CarAppBlockingPolicy}
1131 */
1132 @VisibleForTesting
1133 public void startAppBlockingPolicies() {
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001134 Intent policyIntent = new Intent();
1135 policyIntent.setAction(CarAppBlockingPolicyService.SERVICE_INTERFACE);
1136 List<ResolveInfo> policyInfos = mPackageManager.queryIntentServices(policyIntent, 0);
1137 if (policyInfos == null) { //no need to wait for service binding and retrieval.
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001138 return;
1139 }
1140 LinkedList<AppBlockingPolicyProxy> proxies = new LinkedList<>();
1141 for (ResolveInfo resolveInfo : policyInfos) {
1142 ServiceInfo serviceInfo = resolveInfo.serviceInfo;
1143 if (serviceInfo == null) {
1144 continue;
1145 }
1146 if (serviceInfo.isEnabled()) {
1147 if (mPackageManager.checkPermission(Car.PERMISSION_CONTROL_APP_BLOCKING,
1148 serviceInfo.packageName) != PackageManager.PERMISSION_GRANTED) {
1149 continue;
1150 }
Mayank Gargbfa66132021-05-05 19:56:20 -07001151 Slog.i(TAG, "found policy holding service:" + serviceInfo);
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001152 AppBlockingPolicyProxy proxy = new AppBlockingPolicyProxy(this, mContext,
1153 serviceInfo);
1154 proxy.connect();
1155 proxies.add(proxy);
1156 }
1157 }
Yan Zhu211b1fe2019-11-06 15:54:19 -08001158 synchronized (mLock) {
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001159 mProxies = proxies;
1160 }
1161 }
1162
1163 public void onPolicyConnectionAndSet(AppBlockingPolicyProxy proxy,
1164 CarAppBlockingPolicy policy) {
1165 doHandlePolicyConnection(proxy, policy);
1166 }
1167
1168 public void onPolicyConnectionFailure(AppBlockingPolicyProxy proxy) {
1169 doHandlePolicyConnection(proxy, null);
1170 }
1171
1172 private void doHandlePolicyConnection(AppBlockingPolicyProxy proxy,
1173 CarAppBlockingPolicy policy) {
Yan Zhu211b1fe2019-11-06 15:54:19 -08001174 synchronized (mLock) {
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001175 if (mProxies == null) {
1176 proxy.disconnect();
1177 return;
1178 }
1179 mProxies.remove(proxy);
1180 if (mProxies.size() == 0) {
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001181 mProxies = null;
1182 }
1183 }
1184 try {
1185 if (policy != null) {
Mayank Gargbfa66132021-05-05 19:56:20 -07001186 if (Log.isLoggable(TAG, Log.DEBUG)) {
1187 Slog.d(TAG, "policy setting from policy service:" + proxy.getPackageName());
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001188 }
Keun young Park6c4fd342019-12-13 12:46:04 -08001189 doSetAppBlockingPolicy(proxy.getPackageName(), policy, 0);
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001190 }
1191 } finally {
1192 proxy.disconnect();
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001193 }
1194 }
1195
1196 @Override
Felipe Leme176a5fd2021-01-20 15:48:33 -08001197 public void dump(IndentingPrintWriter writer) {
Yan Zhu211b1fe2019-11-06 15:54:19 -08001198 synchronized (mLock) {
Jordan Jozwiak0aa05982019-06-17 15:14:39 -07001199 writer.println("*CarPackageManagerService*");
Keun-young Park4727da32016-05-31 10:00:51 -07001200 writer.println("mEnableActivityBlocking:" + mEnableActivityBlocking);
Keun young Park40fcb0c2021-09-14 18:47:28 -07001201 writer.println("mPreventTemplatedAppsFromShowingDialog:"
Gaurav Bholaafd79ef2021-06-16 13:22:03 +00001202 + mPreventTemplatedAppsFromShowingDialog);
Keun young Park40fcb0c2021-09-14 18:47:28 -07001203 writer.println("mTemplateActivityClassName:" + mTemplateActivityClassName);
Yao, Yuxingd525de12019-05-06 15:11:48 -07001204 List<String> restrictions = new ArrayList<>(mUxRestrictionsListeners.size());
1205 for (int i = 0; i < mUxRestrictionsListeners.size(); i++) {
1206 int displayId = mUxRestrictionsListeners.keyAt(i);
1207 UxRestrictionsListener listener = mUxRestrictionsListeners.valueAt(i);
1208 restrictions.add(String.format("Display %d is %s",
1209 displayId, (listener.isRestricted() ? "restricted" : "unrestricted")));
1210 }
1211 writer.println("Display Restrictions:\n" + String.join("\n", restrictions));
Jordan Jozwiak0aa05982019-06-17 15:14:39 -07001212 writer.println(" Blocked activity log:");
Bin Tan2536d402021-02-10 15:28:35 -08001213 mBlockedActivityLogs.dump(writer);
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001214 writer.print(dumpPoliciesLocked(true));
Keun young Park40fcb0c2021-09-14 18:47:28 -07001215 writer.print("mCurrentDrivingSafetyRegion:");
1216 writer.println(mCurrentDrivingSafetyRegion);
1217 writer.print("mTempAllowedActivities:");
1218 writer.println(mTempAllowedActivities);
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001219 }
1220 }
1221
Yan Zhu211b1fe2019-11-06 15:54:19 -08001222 @GuardedBy("mLock")
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001223 private String dumpPoliciesLocked(boolean dumpAll) {
1224 StringBuilder sb = new StringBuilder();
1225 if (dumpAll) {
Jordan Jozwiak794abcb2020-07-27 08:08:11 -07001226 sb.append("**System allowlist**\n");
1227 for (AppBlockingPackageInfoWrapper wrapper : mActivityAllowlistMap.values()) {
Ram Periathiruvadi46a3a3d2018-03-23 16:58:32 -07001228 sb.append(wrapper.toString() + "\n");
1229 }
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001230 }
1231 sb.append("**Client Policies**\n");
1232 for (Entry<String, ClientPolicy> entry : mClientPolicies.entrySet()) {
1233 sb.append("Client:" + entry.getKey() + "\n");
Jordan Jozwiak794abcb2020-07-27 08:08:11 -07001234 sb.append(" allowlists:\n");
1235 for (AppBlockingPackageInfoWrapper wrapper : entry.getValue().mAllowlistsMap.values()) {
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001236 sb.append(wrapper.toString() + "\n");
1237 }
Jordan Jozwiak794abcb2020-07-27 08:08:11 -07001238 sb.append(" blocklists:\n");
1239 for (AppBlockingPackageInfoWrapper wrapper : entry.getValue().mBlocklistsMap.values()) {
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001240 sb.append(wrapper.toString() + "\n");
1241 }
1242 }
1243 sb.append("**Unprocessed policy services**\n");
1244 if (mProxies != null) {
1245 for (AppBlockingPolicyProxy proxy : mProxies) {
1246 sb.append(proxy.toString() + "\n");
1247 }
1248 }
Jordan Jozwiak794abcb2020-07-27 08:08:11 -07001249 sb.append("**Allowlist string in resource**\n");
1250 sb.append(mConfiguredAllowlist + "\n");
Ram Periathiruvadi46a3a3d2018-03-23 16:58:32 -07001251
Jordan Jozwiak794abcb2020-07-27 08:08:11 -07001252 sb.append("**System allowlist string in resource**\n");
1253 sb.append(mConfiguredSystemAllowlist + "\n");
Yao, Yuxing0c6fc732019-05-10 14:58:49 -07001254
Jordan Jozwiak794abcb2020-07-27 08:08:11 -07001255 sb.append("**Blocklist string in resource**\n");
1256 sb.append(mConfiguredBlocklist + "\n");
Keun-young Park98960812016-10-04 12:50:54 -07001257
Mayank Gargfde5e662021-01-19 22:21:10 -08001258 sb.append("**Allowlist map from resource**\n");
1259 sb.append(mConfiguredAllowlistMap + "\n");
1260
1261 sb.append("**Blocklist from resource**\n");
1262 sb.append(mConfiguredBlocklist + "\n");
1263
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001264 return sb.toString();
1265 }
1266
Yao, Yuxingd525de12019-05-06 15:11:48 -07001267 /**
1268 * Returns display with physical address.
1269 */
1270 private List<Display> getPhysicalDisplays() {
1271 List<Display> displays = new ArrayList<>();
1272 for (Display display : mDisplayManager.getDisplays()) {
1273 if (display.getAddress() instanceof DisplayAddress.Physical) {
1274 displays.add(display);
1275 }
1276 }
1277 return displays;
1278 }
1279
1280 /**
1281 * Returns whether UX restrictions is required for display.
1282 *
1283 * Non-physical display will use restrictions for {@link Display#DEFAULT_DISPLAY}.
1284 */
1285 private boolean isUxRestrictedOnDisplay(int displayId) {
1286 UxRestrictionsListener listenerForTopTaskDisplay;
1287 if (mUxRestrictionsListeners.indexOfKey(displayId) < 0) {
1288 listenerForTopTaskDisplay = mUxRestrictionsListeners.get(Display.DEFAULT_DISPLAY);
1289 if (listenerForTopTaskDisplay == null) {
1290 // This should never happen.
Mayank Gargbfa66132021-05-05 19:56:20 -07001291 Slog.e(TAG, "Missing listener for default display.");
Yao, Yuxingd525de12019-05-06 15:11:48 -07001292 return true;
1293 }
1294 } else {
1295 listenerForTopTaskDisplay = mUxRestrictionsListeners.get(displayId);
1296 }
1297
1298 return listenerForTopTaskDisplay.isRestricted();
1299 }
1300
1301 private void blockTopActivitiesIfNecessary() {
1302 List<TopTaskInfoContainer> topTasks = mSystemActivityMonitoringService.getTopTasks();
1303 for (TopTaskInfoContainer topTask : topTasks) {
1304 if (topTask == null) {
Mayank Gargbfa66132021-05-05 19:56:20 -07001305 Slog.e(TAG, "Top tasks contains null.");
Yao, Yuxingd525de12019-05-06 15:11:48 -07001306 continue;
1307 }
1308 blockTopActivityIfNecessary(topTask);
1309 }
1310 }
1311
Keun-young Park4727da32016-05-31 10:00:51 -07001312 private void blockTopActivityIfNecessary(TopTaskInfoContainer topTask) {
Gaurav Bhola83173042021-06-21 09:36:20 +00001313 synchronized (mLock) {
Gaurav Bholacb9439b2021-10-06 00:31:20 +00001314 if (!Objects.equals(mActivityBlockingActivity, topTask.topActivity)
Gaurav Bhola3a91fef2021-10-02 00:32:33 +00001315 && mTopActivityWithDialogPerDisplay.contains(topTask.displayId)
Gaurav Bhola83173042021-06-21 09:36:20 +00001316 && !topTask.topActivity.equals(
1317 mTopActivityWithDialogPerDisplay.get(topTask.displayId))) {
1318 // Clear top activity-with-dialog if the activity has changed on this display.
1319 mTopActivityWithDialogPerDisplay.remove(topTask.displayId);
1320 }
1321 }
Yao, Yuxingd525de12019-05-06 15:11:48 -07001322 if (isUxRestrictedOnDisplay(topTask.displayId)) {
1323 doBlockTopActivityIfNotAllowed(topTask);
Yao, Yuxingcfcc59f2019-03-05 16:35:47 -08001324 }
Keun-young Park4727da32016-05-31 10:00:51 -07001325 }
1326
1327 private void doBlockTopActivityIfNotAllowed(TopTaskInfoContainer topTask) {
Ram Periathiruvadi2da6d0e2018-01-26 18:02:10 -08001328 if (topTask.topActivity == null) {
1329 return;
1330 }
Gaurav Bhola83173042021-06-21 09:36:20 +00001331 boolean allowed = isActivityAllowed(topTask);
Mayank Gargbfa66132021-05-05 19:56:20 -07001332 if (Log.isLoggable(TAG, Log.DEBUG)) {
1333 Slog.d(TAG, "new activity:" + topTask.toString() + " allowed:" + allowed);
Keun-young Park4727da32016-05-31 10:00:51 -07001334 }
Ram Periathiruvadibf0eab72018-02-06 12:32:43 -08001335 if (allowed) {
1336 return;
1337 }
Keun young Park40fcb0c2021-09-14 18:47:28 -07001338 if (!mEnableActivityBlocking) {
1339 Slog.d(TAG, "Current activity " + topTask.topActivity
1340 + " not allowed, blocking disabled. Number of tasks in stack:"
1341 + topTask.taskInfo.childTaskIds.length);
1342 return;
Ram Periathiruvadibf0eab72018-02-06 12:32:43 -08001343 }
Mayank Gargbfa66132021-05-05 19:56:20 -07001344 if (Log.isLoggable(TAG, Log.DEBUG)) {
1345 Slog.d(TAG, "Current activity " + topTask.topActivity
Eric Jeong47b1e242020-12-21 13:41:36 -08001346 + " not allowed, will block, number of tasks in stack:"
1347 + topTask.taskInfo.childTaskIds.length);
Keun-young Park4727da32016-05-31 10:00:51 -07001348 }
Yao, Yuxingd1d6a372018-05-08 10:37:43 -07001349
Yao, Yuxing14e83b42018-10-29 18:29:56 -07001350 // Figure out the root activity of blocked task.
1351 String taskRootActivity = null;
Louis Chang3bf2f202020-08-18 13:04:28 +08001352 for (int i = 0; i < topTask.taskInfo.childTaskIds.length; i++) {
Yao, Yuxingd1d6a372018-05-08 10:37:43 -07001353 // topTask.taskId is the task that should be blocked.
Louis Chang3bf2f202020-08-18 13:04:28 +08001354 if (topTask.taskInfo.childTaskIds[i] == topTask.taskId) {
Yao, Yuxingd1d6a372018-05-08 10:37:43 -07001355 // stackInfo represents an ActivityStack. Its fields taskIds and taskNames
1356 // are 1:1 mapped, where taskNames is the name of root activity in this task.
Louis Chang3bf2f202020-08-18 13:04:28 +08001357 taskRootActivity = topTask.taskInfo.childTaskNames[i];
Yao, Yuxingd1d6a372018-05-08 10:37:43 -07001358 break;
1359 }
1360 }
Yao, Yuxing14e83b42018-10-29 18:29:56 -07001361
1362 boolean isRootDO = false;
1363 if (taskRootActivity != null) {
Gaurav Bhola83173042021-06-21 09:36:20 +00001364 ComponentName taskRootComponentName =
1365 ComponentName.unflattenFromString(taskRootActivity);
Yao, Yuxing14e83b42018-10-29 18:29:56 -07001366 isRootDO = isActivityDistractionOptimized(
Gaurav Bhola83173042021-06-21 09:36:20 +00001367 taskRootComponentName.getPackageName(), taskRootComponentName.getClassName());
Yao, Yuxing14e83b42018-10-29 18:29:56 -07001368 }
1369
1370 Intent newActivityIntent = createBlockingActivityIntent(
Yao, Yuxingd525de12019-05-06 15:11:48 -07001371 mActivityBlockingActivity, topTask.displayId,
1372 topTask.topActivity.flattenToShortString(), topTask.taskId, taskRootActivity,
1373 isRootDO);
Yao, Yuxing14e83b42018-10-29 18:29:56 -07001374
1375 // Intent contains all info to debug what is blocked - log into both logcat and dumpsys.
1376 String log = "Starting blocking activity with intent: " + newActivityIntent.toUri(0);
Mayank Gargbfa66132021-05-05 19:56:20 -07001377 if (Log.isLoggable(TAG, Log.INFO)) {
1378 Slog.i(TAG, log);
Yao, Yuxing14e83b42018-10-29 18:29:56 -07001379 }
Bin Tan2536d402021-02-10 15:28:35 -08001380 mBlockedActivityLogs.log(log);
Ram Periathiruvadi38388302018-02-22 16:42:49 -08001381 mSystemActivityMonitoringService.blockActivity(topTask, newActivityIntent);
Keun-young Park4727da32016-05-31 10:00:51 -07001382 }
1383
Gaurav Bhola83173042021-06-21 09:36:20 +00001384 private boolean isActivityAllowed(TopTaskInfoContainer topTaskInfoContainer) {
1385 ComponentName activityName = topTaskInfoContainer.topActivity;
Gaurav Bholaafd79ef2021-06-16 13:22:03 +00001386 boolean isDistractionOptimized = isActivityDistractionOptimized(
1387 activityName.getPackageName(),
1388 activityName.getClassName());
1389 if (!isDistractionOptimized) {
1390 return false;
1391 }
1392 return !(mPreventTemplatedAppsFromShowingDialog
1393 && isTemplateActivity(activityName)
Gaurav Bhola83173042021-06-21 09:36:20 +00001394 && isActivityShowingADialogOnDisplay(activityName, topTaskInfoContainer.displayId));
Gaurav Bholaafd79ef2021-06-16 13:22:03 +00001395 }
1396
1397 private boolean isTemplateActivity(ComponentName activityName) {
1398 // TODO(b/191263486): Finalise on how to detect the templated activities.
1399 return activityName.getClassName().equals(mTemplateActivityClassName);
1400 }
1401
Gaurav Bhola83173042021-06-21 09:36:20 +00001402 private boolean isActivityShowingADialogOnDisplay(ComponentName activityName, int displayId) {
Gaurav Bholaafd79ef2021-06-16 13:22:03 +00001403 String output = dumpWindows();
1404 List<WindowDumpParser.Window> appWindows =
Gaurav Bhola83173042021-06-21 09:36:20 +00001405 WindowDumpParser.getParsedAppWindows(output, activityName.getPackageName());
Gaurav Bhola38569c72021-06-30 15:36:20 +00001406 // TODO(b/192354699): Handle case where an activity can have multiple instances on the same
1407 // display.
1408 int totalAppWindows = appWindows.size();
1409 String firstActivityRecord = null;
1410 int numTopActivityAppWindowsOnDisplay = 0;
1411 for (int i = 0; i < totalAppWindows; i++) {
1412 WindowDumpParser.Window appWindow = appWindows.get(i);
1413 if (appWindow.getDisplayId() != displayId) {
1414 continue;
1415 }
1416 if (TextUtils.isEmpty(appWindow.getActivityRecord())) {
1417 continue;
1418 }
1419 if (firstActivityRecord == null) {
1420 firstActivityRecord = appWindow.getActivityRecord();
1421 }
1422 if (firstActivityRecord.equals(appWindow.getActivityRecord())) {
1423 numTopActivityAppWindowsOnDisplay++;
1424 }
Gaurav Bholaafd79ef2021-06-16 13:22:03 +00001425 }
Gaurav Bhola83173042021-06-21 09:36:20 +00001426 Slogf.d(TAG, "Top activity = " + activityName);
Gaurav Bhola38569c72021-06-30 15:36:20 +00001427 Slogf.d(TAG, "Number of app widows of top activity = " + numTopActivityAppWindowsOnDisplay);
1428 boolean isShowingADialog = numTopActivityAppWindowsOnDisplay > 1;
Gaurav Bhola83173042021-06-21 09:36:20 +00001429 synchronized (mLock) {
1430 if (isShowingADialog) {
1431 mTopActivityWithDialogPerDisplay.put(displayId, activityName);
1432 } else {
1433 mTopActivityWithDialogPerDisplay.remove(displayId);
Gaurav Bholaafd79ef2021-06-16 13:22:03 +00001434 }
1435 }
Gaurav Bhola83173042021-06-21 09:36:20 +00001436 return isShowingADialog;
Gaurav Bholaafd79ef2021-06-16 13:22:03 +00001437 }
1438
1439 private String dumpWindows() {
1440 try {
1441 ParcelFileDescriptor[] fileDescriptors = ParcelFileDescriptor.createSocketPair();
1442 mWindowManagerBinder.dump(
1443 fileDescriptors[0].getFileDescriptor(), WINDOW_DUMP_ARGUMENTS);
1444 fileDescriptors[0].close();
1445 StringBuilder outputBuilder = new StringBuilder();
1446 BufferedReader reader = new BufferedReader(
1447 new FileReader(fileDescriptors[1].getFileDescriptor()));
1448 String line;
1449 while ((line = reader.readLine()) != null) {
1450 outputBuilder.append(line).append("\n");
1451 }
1452 reader.close();
1453 fileDescriptors[1].close();
1454 return outputBuilder.toString();
1455 } catch (IOException | RemoteException e) {
1456 throw new RuntimeException(e);
1457 }
1458 }
1459
Yao, Yuxing14e83b42018-10-29 18:29:56 -07001460 /**
1461 * Creates an intent to start blocking activity.
1462 *
1463 * @param blockingActivity the activity to launch
Jordan Jozwiak12d59e02019-06-20 18:10:21 -07001464 * @param blockedActivity the activity being blocked
1465 * @param blockedTaskId the blocked task id, which contains the blocked activity
Yao, Yuxing14e83b42018-10-29 18:29:56 -07001466 * @param taskRootActivity root activity of the blocked task
Gaurav Bhola83173042021-06-21 09:36:20 +00001467 * @param isRootDo denotes if the root activity is distraction optimised
Yao, Yuxing14e83b42018-10-29 18:29:56 -07001468 * @return an intent to launch the blocking activity.
1469 */
1470 private static Intent createBlockingActivityIntent(ComponentName blockingActivity,
Yao, Yuxingd525de12019-05-06 15:11:48 -07001471 int displayId, String blockedActivity, int blockedTaskId, String taskRootActivity,
1472 boolean isRootDo) {
Yao, Yuxing14e83b42018-10-29 18:29:56 -07001473 Intent newActivityIntent = new Intent();
Yao, Yuxingd525de12019-05-06 15:11:48 -07001474 newActivityIntent.setFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
Yao, Yuxing14e83b42018-10-29 18:29:56 -07001475 newActivityIntent.setComponent(blockingActivity);
1476 newActivityIntent.putExtra(
Yao, Yuxingd525de12019-05-06 15:11:48 -07001477 BLOCKING_INTENT_EXTRA_DISPLAY_ID, displayId);
1478 newActivityIntent.putExtra(
Yao, Yuxing14e83b42018-10-29 18:29:56 -07001479 BLOCKING_INTENT_EXTRA_BLOCKED_ACTIVITY_NAME, blockedActivity);
1480 newActivityIntent.putExtra(
1481 BLOCKING_INTENT_EXTRA_BLOCKED_TASK_ID, blockedTaskId);
1482 newActivityIntent.putExtra(
1483 BLOCKING_INTENT_EXTRA_ROOT_ACTIVITY_NAME, taskRootActivity);
1484 newActivityIntent.putExtra(
1485 BLOCKING_INTENT_EXTRA_IS_ROOT_ACTIVITY_DO, isRootDo);
Yao, Yuxingcfcc59f2019-03-05 16:35:47 -08001486
Yao, Yuxing14e83b42018-10-29 18:29:56 -07001487 return newActivityIntent;
1488 }
1489
Ram Periathiruvadicdee1202018-07-17 18:01:31 -07001490 /**
1491 * Enable/Disable activity blocking by correspondingly enabling/disabling broadcasting UXR
1492 * changes in {@link CarUxRestrictionsManagerService}. This is only available in
1493 * engineering builds for development convenience.
Ram Periathiruvadicdee1202018-07-17 18:01:31 -07001494 */
Ram Periathiruvadia6e0d9b2018-04-25 20:19:22 -07001495 @Override
Yan Zhu211b1fe2019-11-06 15:54:19 -08001496 public void setEnableActivityBlocking(boolean enable) {
Ram Periathiruvadicdee1202018-07-17 18:01:31 -07001497 if (!isDebugBuild()) {
Mayank Gargbfa66132021-05-05 19:56:20 -07001498 Slog.e(TAG, "Cannot enable/disable activity blocking");
Ram Periathiruvadicdee1202018-07-17 18:01:31 -07001499 return;
1500 }
Yan Zhu211b1fe2019-11-06 15:54:19 -08001501
Ram Periathiruvadia6e0d9b2018-04-25 20:19:22 -07001502 // Check if the caller has the same signature as that of the car service.
1503 if (mPackageManager.checkSignatures(Process.myUid(), Binder.getCallingUid())
1504 != PackageManager.SIGNATURE_MATCH) {
1505 throw new SecurityException(
1506 "Caller " + mPackageManager.getNameForUid(Binder.getCallingUid())
Mayank Garg31e73042020-01-23 00:10:38 -08001507 + " does not have the right signature");
Ram Periathiruvadia6e0d9b2018-04-25 20:19:22 -07001508 }
Ram Periathiruvadicdee1202018-07-17 18:01:31 -07001509 mCarUxRestrictionsService.setUxRChangeBroadcastEnabled(enable);
Ram Periathiruvadibf0eab72018-02-06 12:32:43 -08001510 }
1511
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001512 /**
Ram Periathiruvadi38388302018-02-22 16:42:49 -08001513 * Get the distraction optimized activities for the given package.
1514 *
1515 * @param pkgName Name of the package
1516 * @return Array of the distraction optimized activities in the package
1517 */
1518 @Nullable
1519 public String[] getDistractionOptimizedActivities(String pkgName) {
1520 try {
Keun young Park40fcb0c2021-09-14 18:47:28 -07001521 return findDistractionOptimizedActivitiesAsUser(pkgName,
Yao, Yuxing0c6fc732019-05-10 14:58:49 -07001522 mActivityManager.getCurrentUser());
Ram Periathiruvadi38388302018-02-22 16:42:49 -08001523 } catch (NameNotFoundException e) {
1524 return null;
1525 }
1526 }
Ram Periathiruvadie6e2ac32018-05-02 14:57:46 -07001527
Keun young Park40fcb0c2021-09-14 18:47:28 -07001528 private String[] findDistractionOptimizedActivitiesAsUser(String pkgName, int userId)
1529 throws NameNotFoundException {
1530 String regionString;
1531 synchronized (mLock) {
1532 regionString = mCurrentDrivingSafetyRegion;
1533 }
1534 return CarAppMetadataReader.findDistractionOptimizedActivitiesAsUser(mContext, pkgName,
1535 userId, regionString);
1536 }
1537
Ram Periathiruvadi38388302018-02-22 16:42:49 -08001538 /**
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001539 * Reading policy and setting policy can take time. Run it in a separate handler thread.
1540 */
Keun young Parkb241d022020-04-20 20:31:34 -07001541 private static final class PackageHandler extends Handler {
Mayank Garg72c71d22021-02-03 23:54:45 -08001542 private static final String TAG = CarLog.tagFor(CarPackageManagerService.class);
Keun young Parkb241d022020-04-20 20:31:34 -07001543
Keun young Park6c4fd342019-12-13 12:46:04 -08001544 private static final int MSG_INIT = 0;
1545 private static final int MSG_PARSE_PKG = 1;
1546 private static final int MSG_UPDATE_POLICY = 2;
1547 private static final int MSG_RELEASE = 3;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001548
Keun young Parkb241d022020-04-20 20:31:34 -07001549 private final WeakReference<CarPackageManagerService> mService;
1550
1551 private PackageHandler(Looper looper, CarPackageManagerService service) {
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001552 super(looper);
Keun young Parkb241d022020-04-20 20:31:34 -07001553 mService = new WeakReference<CarPackageManagerService>(service);
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001554 }
1555
1556 private void requestInit() {
1557 Message msg = obtainMessage(MSG_INIT);
1558 sendMessage(msg);
1559 }
1560
1561 private void requestRelease() {
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001562 removeMessages(MSG_UPDATE_POLICY);
Keun-young Park6dcc50b2016-10-10 19:01:11 -07001563 Message msg = obtainMessage(MSG_RELEASE);
1564 sendMessage(msg);
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001565 }
1566
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001567 private void requestUpdatingPolicy(String packageName, CarAppBlockingPolicy policy,
1568 int flags) {
1569 Pair<String, CarAppBlockingPolicy> pair = new Pair<>(packageName, policy);
1570 Message msg = obtainMessage(MSG_UPDATE_POLICY, flags, 0, pair);
1571 sendMessage(msg);
1572 }
1573
Mayank Gargfde5e662021-01-19 22:21:10 -08001574 private void requestParsingInstalledPkg(String packageName) {
1575 Message msg = obtainMessage(MSG_PARSE_PKG, packageName);
1576 sendMessage(msg);
Ram Periathiruvadi38388302018-02-22 16:42:49 -08001577 }
1578
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001579 @Override
1580 public void handleMessage(Message msg) {
Keun young Parkb241d022020-04-20 20:31:34 -07001581 CarPackageManagerService service = mService.get();
1582 if (service == null) {
Eric Jeong47b1e242020-12-21 13:41:36 -08001583 Slog.i(TAG, "handleMessage null service");
Keun young Parkb241d022020-04-20 20:31:34 -07001584 return;
1585 }
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001586 switch (msg.what) {
1587 case MSG_INIT:
Keun young Parkb241d022020-04-20 20:31:34 -07001588 service.doHandleInit();
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001589 break;
Ram Periathiruvadi38388302018-02-22 16:42:49 -08001590 case MSG_PARSE_PKG:
Mayank Gargfde5e662021-01-19 22:21:10 -08001591 service.doParseInstalledPackage((String) msg.obj);
Ram Periathiruvadi38388302018-02-22 16:42:49 -08001592 break;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001593 case MSG_UPDATE_POLICY:
1594 Pair<String, CarAppBlockingPolicy> pair =
1595 (Pair<String, CarAppBlockingPolicy>) msg.obj;
Keun young Parkb241d022020-04-20 20:31:34 -07001596 service.doUpdatePolicy(pair.first, pair.second, msg.arg1);
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001597 break;
Keun-young Park6dcc50b2016-10-10 19:01:11 -07001598 case MSG_RELEASE:
Keun young Parkb241d022020-04-20 20:31:34 -07001599 service.doHandleRelease();
Keun-young Park6dcc50b2016-10-10 19:01:11 -07001600 break;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001601 }
1602 }
1603 }
1604
1605 private static class AppBlockingPackageInfoWrapper {
1606 private final AppBlockingPackageInfo info;
1607 /**
1608 * Whether the current info is matching with the target package in system. Mismatch can
1609 * happen for version out of range or signature mismatch.
1610 */
1611 private boolean isMatching;
1612
1613 private AppBlockingPackageInfoWrapper(AppBlockingPackageInfo info, boolean isMatching) {
Ram Periathiruvadie6e2ac32018-05-02 14:57:46 -07001614 this.info = info;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001615 this.isMatching = isMatching;
1616 }
1617
1618 @Override
1619 public String toString() {
1620 return "AppBlockingPackageInfoWrapper [info=" + info + ", isMatching=" + isMatching +
1621 "]";
1622 }
1623 }
1624
1625 /**
1626 * Client policy holder per each client. Should be accessed with CarpackageManagerService.this
1627 * held.
1628 */
1629 private static class ClientPolicy {
Jordan Jozwiak794abcb2020-07-27 08:08:11 -07001630 private final HashMap<String, AppBlockingPackageInfoWrapper> mAllowlistsMap =
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001631 new HashMap<>();
Jordan Jozwiak794abcb2020-07-27 08:08:11 -07001632 private final HashMap<String, AppBlockingPackageInfoWrapper> mBlocklistsMap =
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001633 new HashMap<>();
1634
Jordan Jozwiak794abcb2020-07-27 08:08:11 -07001635 private void replaceAllowlists(AppBlockingPackageInfoWrapper[] allowlists) {
1636 mAllowlistsMap.clear();
1637 addToAllowlists(allowlists);
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001638 }
1639
Jordan Jozwiak794abcb2020-07-27 08:08:11 -07001640 private void addToAllowlists(AppBlockingPackageInfoWrapper[] allowlists) {
1641 if (allowlists == null) {
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001642 return;
1643 }
Jordan Jozwiak794abcb2020-07-27 08:08:11 -07001644 for (AppBlockingPackageInfoWrapper wrapper : allowlists) {
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001645 if (wrapper != null) {
Jordan Jozwiak794abcb2020-07-27 08:08:11 -07001646 mAllowlistsMap.put(wrapper.info.packageName, wrapper);
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001647 }
1648 }
1649 }
1650
Jordan Jozwiak794abcb2020-07-27 08:08:11 -07001651 private void removeAllowlists(AppBlockingPackageInfoWrapper[] allowlists) {
1652 if (allowlists == null) {
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001653 return;
1654 }
Jordan Jozwiak794abcb2020-07-27 08:08:11 -07001655 for (AppBlockingPackageInfoWrapper wrapper : allowlists) {
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001656 if (wrapper != null) {
Jordan Jozwiak794abcb2020-07-27 08:08:11 -07001657 mAllowlistsMap.remove(wrapper.info.packageName);
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001658 }
1659 }
1660 }
1661
Jordan Jozwiak794abcb2020-07-27 08:08:11 -07001662 private void replaceBlocklists(AppBlockingPackageInfoWrapper[] blocklists) {
1663 mBlocklistsMap.clear();
1664 addToBlocklists(blocklists);
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001665 }
1666
Jordan Jozwiak794abcb2020-07-27 08:08:11 -07001667 private void addToBlocklists(AppBlockingPackageInfoWrapper[] blocklists) {
1668 if (blocklists == null) {
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001669 return;
1670 }
Jordan Jozwiak794abcb2020-07-27 08:08:11 -07001671 for (AppBlockingPackageInfoWrapper wrapper : blocklists) {
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001672 if (wrapper != null) {
Jordan Jozwiak794abcb2020-07-27 08:08:11 -07001673 mBlocklistsMap.put(wrapper.info.packageName, wrapper);
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001674 }
1675 }
1676 }
1677
Jordan Jozwiak794abcb2020-07-27 08:08:11 -07001678 private void removeBlocklists(AppBlockingPackageInfoWrapper[] blocklists) {
1679 if (blocklists == null) {
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001680 return;
1681 }
Jordan Jozwiak794abcb2020-07-27 08:08:11 -07001682 for (AppBlockingPackageInfoWrapper wrapper : blocklists) {
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001683 if (wrapper != null) {
Jordan Jozwiak794abcb2020-07-27 08:08:11 -07001684 mBlocklistsMap.remove(wrapper.info.packageName);
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001685 }
1686 }
1687 }
1688 }
Keun-young Park4727da32016-05-31 10:00:51 -07001689
1690 private class ActivityLaunchListener
Ram Periathiruvadie6e2ac32018-05-02 14:57:46 -07001691 implements SystemActivityMonitoringService.ActivityLaunchListener {
Keun-young Park4727da32016-05-31 10:00:51 -07001692 @Override
1693 public void onActivityLaunch(TopTaskInfoContainer topTask) {
Yao, Yuxing2646cff2019-04-23 17:01:26 -07001694 if (topTask == null) {
Mayank Gargbfa66132021-05-05 19:56:20 -07001695 Slog.e(TAG, "Received callback with null top task.");
Yao, Yuxing2646cff2019-04-23 17:01:26 -07001696 return;
1697 }
Keun-young Park4727da32016-05-31 10:00:51 -07001698 blockTopActivityIfNecessary(topTask);
1699 }
1700 }
1701
Ram Periathiruvadi2da6d0e2018-01-26 18:02:10 -08001702 /**
1703 * Listens to the UX restrictions from {@link CarUxRestrictionsManagerService} and initiates
1704 * checking if the foreground Activity should be blocked.
1705 */
1706 private class UxRestrictionsListener extends ICarUxRestrictionsChangeListener.Stub {
Yan Zhu211b1fe2019-11-06 15:54:19 -08001707 @GuardedBy("mLock")
Ram Periathiruvadi2da6d0e2018-01-26 18:02:10 -08001708 @Nullable
1709 private CarUxRestrictions mCurrentUxRestrictions;
1710 private final CarUxRestrictionsManagerService uxRestrictionsService;
Keun-young Park4727da32016-05-31 10:00:51 -07001711
Ram Periathiruvadi2da6d0e2018-01-26 18:02:10 -08001712 public UxRestrictionsListener(CarUxRestrictionsManagerService service) {
1713 uxRestrictionsService = service;
Ram Periathiruvadi2da6d0e2018-01-26 18:02:10 -08001714 }
1715
1716 @Override
1717 public void onUxRestrictionsChanged(CarUxRestrictions restrictions) {
Mayank Gargbfa66132021-05-05 19:56:20 -07001718 if (Log.isLoggable(TAG, Log.DEBUG)) {
1719 Slog.d(TAG, "Received uxr restrictions: "
1720 + restrictions.isRequiresDistractionOptimization() + " : "
1721 + restrictions.getActiveRestrictions());
Ram Periathiruvadi2da6d0e2018-01-26 18:02:10 -08001722 }
Ram Periathiruvadic57678d2018-04-23 09:18:33 -07001723
Yan Zhu211b1fe2019-11-06 15:54:19 -08001724 synchronized (mLock) {
Ram Periathiruvadi2da6d0e2018-01-26 18:02:10 -08001725 mCurrentUxRestrictions = new CarUxRestrictions(restrictions);
1726 }
1727 checkIfTopActivityNeedsBlocking();
1728 }
1729
1730 private void checkIfTopActivityNeedsBlocking() {
1731 boolean shouldCheck = false;
Yan Zhu211b1fe2019-11-06 15:54:19 -08001732 synchronized (mLock) {
Ram Periathiruvadi2da6d0e2018-01-26 18:02:10 -08001733 if (mCurrentUxRestrictions != null
1734 && mCurrentUxRestrictions.isRequiresDistractionOptimization()) {
1735 shouldCheck = true;
Keun-young Park4727da32016-05-31 10:00:51 -07001736 }
1737 }
Mayank Gargbfa66132021-05-05 19:56:20 -07001738 if (Log.isLoggable(TAG, Log.DEBUG)) {
1739 Slog.d(TAG, "Should check top tasks?: " + shouldCheck);
Ram Periathiruvadi2da6d0e2018-01-26 18:02:10 -08001740 }
1741 if (shouldCheck) {
Yao, Yuxingd525de12019-05-06 15:11:48 -07001742 // Loop over all top tasks to ensure tasks on virtual display can also be blocked.
Keun-young Park4727da32016-05-31 10:00:51 -07001743 blockTopActivitiesIfNecessary();
1744 }
1745 }
1746
Yan Zhu211b1fe2019-11-06 15:54:19 -08001747 private boolean isRestricted() {
Ram Periathiruvadi2da6d0e2018-01-26 18:02:10 -08001748 // if current restrictions is null, try querying the service, once.
Yan Zhu211b1fe2019-11-06 15:54:19 -08001749 synchronized (mLock) {
1750 if (mCurrentUxRestrictions == null) {
1751 mCurrentUxRestrictions = uxRestrictionsService.getCurrentUxRestrictions();
1752 }
1753 if (mCurrentUxRestrictions != null) {
1754 return mCurrentUxRestrictions.isRequiresDistractionOptimization();
1755 }
Ram Periathiruvadi2da6d0e2018-01-26 18:02:10 -08001756 }
Yan Zhu211b1fe2019-11-06 15:54:19 -08001757
Ram Periathiruvadi2da6d0e2018-01-26 18:02:10 -08001758 // If restriction information is still not available (could happen during bootup),
1759 // return not restricted. This maintains parity with previous implementation but needs
1760 // a revisit as we test more.
1761 return false;
Keun-young Park4727da32016-05-31 10:00:51 -07001762 }
1763 }
Ram Periathiruvadi38388302018-02-22 16:42:49 -08001764
1765 /**
Gaurav Bholaafd79ef2021-06-16 13:22:03 +00001766 * Called when a window change event is received by the {@link CarSafetyAccessibilityService}.
1767 */
1768 @VisibleForTesting
1769 void onWindowChangeEvent() {
1770 Slogf.d(TAG, "onWindowChange event received");
1771 mHandlerThread.getThreadHandler().post(() -> blockTopActivitiesIfNecessary());
1772 }
1773
1774 /**
Ram Periathiruvadie6e2ac32018-05-02 14:57:46 -07001775 * Listens to the package install/uninstall events to know when to initiate parsing
1776 * installed packages.
1777 */
1778 private class PackageParsingEventReceiver extends BroadcastReceiver {
Ram Periathiruvadie6e2ac32018-05-02 14:57:46 -07001779 @Override
1780 public void onReceive(Context context, Intent intent) {
1781 if (intent == null || intent.getAction() == null) {
1782 return;
1783 }
Mayank Gargbfa66132021-05-05 19:56:20 -07001784 if (Log.isLoggable(TAG, Log.DEBUG)) {
1785 Slog.d(TAG, "PackageParsingEventReceiver Received " + intent.getAction());
Ram Periathiruvadie6e2ac32018-05-02 14:57:46 -07001786 }
1787 String action = intent.getAction();
1788 if (isPackageManagerAction(action)) {
Ram Periathiruvadi295954d2018-04-10 18:27:28 -07001789 // send a delayed message so if we received multiple related intents, we parse
1790 // only once.
1791 logEventChange(intent);
Mayank Gargfde5e662021-01-19 22:21:10 -08001792 String packageName = getPackageName(intent);
1793 mHandler.requestParsingInstalledPkg(packageName);
Ram Periathiruvadi295954d2018-04-10 18:27:28 -07001794 }
1795 }
1796
Mayank Gargfde5e662021-01-19 22:21:10 -08001797 private String getPackageName(Intent intent) {
1798 // For mPackageManagerActions, data should contain package name.
1799 String dataString = intent.getDataString();
1800 if (dataString == null) return null;
1801
1802 String scheme = intent.getScheme();
1803 if (!scheme.equals("package")) return null;
1804
1805 String[] splitData = intent.getDataString().split(":");
1806 if (splitData.length < 2) return null;
1807
1808 return splitData[1];
1809 }
1810
Ram Periathiruvadi295954d2018-04-10 18:27:28 -07001811 private boolean isPackageManagerAction(String action) {
Jordan Jozwiak12d59e02019-06-20 18:10:21 -07001812 return mPackageManagerActions.contains(action);
Ram Periathiruvadi295954d2018-04-10 18:27:28 -07001813 }
1814
1815 /**
1816 * Convenience log function to log what changed. Logs only when more debug logs
1817 * are needed - DBG_POLICY_CHECK needs to be true
1818 */
1819 private void logEventChange(Intent intent) {
Mayank Gargbfa66132021-05-05 19:56:20 -07001820 if (intent == null) {
Ram Periathiruvadi295954d2018-04-10 18:27:28 -07001821 return;
1822 }
Mayank Gargbfa66132021-05-05 19:56:20 -07001823 if (Log.isLoggable(TAG, Log.DEBUG)) {
1824 String packageName = intent.getData().getSchemeSpecificPart();
1825 Slog.d(TAG, "Pkg Changed:" + packageName);
1826 String action = intent.getAction();
1827 if (action == null) {
1828 return;
Ram Periathiruvadi295954d2018-04-10 18:27:28 -07001829 }
Mayank Gargbfa66132021-05-05 19:56:20 -07001830 if (action.equals(Intent.ACTION_PACKAGE_CHANGED)) {
1831 Slog.d(TAG, "Changed components");
1832 String[] cc = intent
1833 .getStringArrayExtra(Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST);
1834 if (cc != null) {
1835 for (String c : cc) {
1836 Slog.d(TAG, c);
1837 }
1838 }
1839 } else if (action.equals(Intent.ACTION_PACKAGE_REMOVED)
1840 || action.equals(Intent.ACTION_PACKAGE_ADDED)) {
1841 Slog.d(TAG, action + " Replacing?: "
1842 + intent.getBooleanExtra(Intent.EXTRA_REPLACING, false));
1843 }
Ram Periathiruvadi38388302018-02-22 16:42:49 -08001844 }
1845 }
1846 }
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001847}