blob: fb11fd8366330ad41db18bcdf2919b43980aa1d1 [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);
Ram Periathiruvadid937c322018-06-13 12:28:12 -0700276 mAllowedAppInstallSources = Arrays.asList(
277 res.getStringArray(R.array.allowedAppInstallSources));
Pavel Maltsev38da4312019-04-08 10:38:38 -0700278 mVendorServiceController = new VendorServiceController(
Anthony Hughfbb67762019-10-15 12:54:54 -0700279 mContext, mHandler.getLooper());
Gaurav Bholaafd79ef2021-06-16 13:22:03 +0000280 mPreventTemplatedAppsFromShowingDialog =
281 res.getBoolean(R.bool.config_preventTemplatedAppsFromShowingDialog);
282 mTemplateActivityClassName = res.getString(R.string.config_template_activity_class_name);
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800283 }
284
Ram Periathiruvadid937c322018-06-13 12:28:12 -0700285
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800286 @Override
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800287 public void setAppBlockingPolicy(String packageName, CarAppBlockingPolicy policy, int flags) {
Mayank Gargbfa66132021-05-05 19:56:20 -0700288 if (Log.isLoggable(TAG, Log.DEBUG)) {
289 Slog.d(TAG, "policy setting from binder call, client:" + packageName);
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800290 }
Keun young Park6c4fd342019-12-13 12:46:04 -0800291 doSetAppBlockingPolicy(packageName, policy, flags);
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800292 }
293
Yao, Yuxingd1d6a372018-05-08 10:37:43 -0700294 /**
295 * Restarts the requested task. If task with {@code taskId} does not exist, do nothing.
296 */
297 @Override
298 public void restartTask(int taskId) {
Keun young Park572023a2020-06-03 17:29:36 -0700299 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.REAL_GET_TASKS)
300 != PackageManager.PERMISSION_GRANTED) {
301 throw new SecurityException(
302 "requires permission " + android.Manifest.permission.REAL_GET_TASKS);
303 }
Yao, Yuxingd1d6a372018-05-08 10:37:43 -0700304 mSystemActivityMonitoringService.restartTask(taskId);
305 }
306
Keun young Park40fcb0c2021-09-14 18:47:28 -0700307 @Override
308 public String getCurrentDrivingSafetyRegion() {
309 assertAppBlockingOrDrivingStatePermission();
310 synchronized (mLock) {
311 return mCurrentDrivingSafetyRegion;
312 }
313 }
314
315 private String getComponentNameString(String packageName, String className) {
316 return packageName + '/' + className;
317 }
318
319 @Override
320 public void controlOneTimeActivityBlockingBypassingAsUser(String packageName,
321 String activityClassName, boolean bypass, @UserIdInt int userId) {
322 assertAppBlockingPermission();
323 if (!callerCanQueryPackage(packageName)) {
324 throw new SecurityException("cannot query other package");
325 }
326 try {
327 // Read this to check the validity of pkg / activity name. Not checking this can allow
328 // bad apps to be allowed later.
329 CarAppMetadataReader.getSupportedDrivingSafetyRegionsForActivityAsUser(mContext,
330 packageName, activityClassName, userId);
331 } catch (NameNotFoundException e) {
332 throw new ServiceSpecificException(CarPackageManager.ERROR_CODE_NO_PACKAGE,
333 e.getMessage());
334 }
335 String componentName = getComponentNameString(packageName, activityClassName);
336 synchronized (mLock) {
337 if (bypass) {
338 mTempAllowedActivities.add(componentName);
339 } else {
340 mTempAllowedActivities.remove(componentName);
341 }
342 }
343 if (!bypass) { // block top activities if bypassing is disabled.
344 blockTopActivitiesIfNecessary();
345 }
346 }
347
348 @GuardedBy("mLock")
349 private void resetTempAllowedActivitiesLocked() {
350 mTempAllowedActivities.clear();
351 }
352
353 @Override
354 public List<String> getSupportedDrivingSafetyRegionsForActivityAsUser(String packageName,
355 String activityClassName, @UserIdInt int userId) {
356 assertAppBlockingOrDrivingStatePermission();
357 if (!callerCanQueryPackage(packageName)) {
358 throw new SecurityException("cannot query other package");
359 }
360 long token = Binder.clearCallingIdentity();
361 try {
362 return CarAppMetadataReader.getSupportedDrivingSafetyRegionsForActivityAsUser(mContext,
363 packageName, activityClassName, userId);
364 } catch (NameNotFoundException e) {
365 throw new ServiceSpecificException(CarPackageManager.ERROR_CODE_NO_PACKAGE,
366 e.getMessage());
367 } finally {
368 Binder.restoreCallingIdentity(token);
369 }
370 }
371
372 private void assertAppBlockingOrDrivingStatePermission() {
373 if (mContext.checkCallingOrSelfPermission(Car.PERMISSION_CONTROL_APP_BLOCKING)
374 != PackageManager.PERMISSION_GRANTED && mContext.checkCallingOrSelfPermission(
375 Car.PERMISSION_CAR_DRIVING_STATE) != PackageManager.PERMISSION_GRANTED) {
376 throw new SecurityException(
377 "requires permission " + Car.PERMISSION_CONTROL_APP_BLOCKING + " or "
378 + Car.PERMISSION_CAR_DRIVING_STATE);
379 }
380 }
381
382 private void assertAppBlockingPermission() {
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800383 if (mContext.checkCallingOrSelfPermission(Car.PERMISSION_CONTROL_APP_BLOCKING)
384 != PackageManager.PERMISSION_GRANTED) {
385 throw new SecurityException(
386 "requires permission " + Car.PERMISSION_CONTROL_APP_BLOCKING);
387 }
Keun young Park40fcb0c2021-09-14 18:47:28 -0700388 }
389
390 private void doSetAppBlockingPolicy(String packageName, CarAppBlockingPolicy policy,
391 int flags) {
392 assertAppBlockingPermission();
Enrico Granata3da3c612017-01-20 15:24:30 -0800393 CarServiceUtils.assertPackageName(mContext, packageName);
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800394 if (policy == null) {
395 throw new IllegalArgumentException("policy cannot be null");
396 }
397 if ((flags & CarPackageManager.FLAG_SET_POLICY_ADD) != 0 &&
398 (flags & CarPackageManager.FLAG_SET_POLICY_REMOVE) != 0) {
399 throw new IllegalArgumentException(
400 "Cannot set both FLAG_SET_POLICY_ADD and FLAG_SET_POLICY_REMOVE flag");
401 }
Keun young Park6c4fd342019-12-13 12:46:04 -0800402 synchronized (mLock) {
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800403 if ((flags & CarPackageManager.FLAG_SET_POLICY_WAIT_FOR_CHANGE) != 0) {
Keun young Park6c4fd342019-12-13 12:46:04 -0800404 mWaitingPolicies.add(policy);
405 }
406 }
407 mHandler.requestUpdatingPolicy(packageName, policy, flags);
408 if ((flags & CarPackageManager.FLAG_SET_POLICY_WAIT_FOR_CHANGE) != 0) {
409 synchronized (mLock) {
410 try {
411 while (mWaitingPolicies.contains(policy)) {
Keun young Parkff3196b2020-01-07 12:44:10 -0800412 mLock.wait();
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800413 }
Keun young Park6c4fd342019-12-13 12:46:04 -0800414 } catch (InterruptedException e) {
415 // Pass it over binder call
416 throw new IllegalStateException(
417 "Interrupted while waiting for policy completion", e);
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800418 }
419 }
420 }
421 }
422
423 @Override
Ram Periathiruvadie154f582018-03-21 21:53:27 -0700424 public boolean isActivityDistractionOptimized(String packageName, String className) {
Mayank Garg892160e2021-03-22 22:43:23 -0700425 if (!callerCanQueryPackage(packageName)) return false;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800426 assertPackageAndClassName(packageName, className);
Yan Zhu211b1fe2019-11-06 15:54:19 -0800427 synchronized (mLock) {
Mayank Gargbfa66132021-05-05 19:56:20 -0700428 if (Log.isLoggable(TAG, Log.DEBUG)) {
429 Slog.d(TAG, "isActivityDistractionOptimized" + dumpPoliciesLocked(false));
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800430 }
Mayank Gargfde5e662021-01-19 22:21:10 -0800431
Keun young Park40fcb0c2021-09-14 18:47:28 -0700432 if (mTempAllowedActivities.contains(getComponentNameString(packageName,
433 className))) {
434 return true;
435 }
436
Gaurav Bhola83173042021-06-21 09:36:20 +0000437 for (int i = mTopActivityWithDialogPerDisplay.size() - 1; i >= 0; i--) {
438 ComponentName activityWithDialog = mTopActivityWithDialogPerDisplay.get(
439 mTopActivityWithDialogPerDisplay.keyAt(i));
440 if (activityWithDialog.getClassName().equals(className)
441 && activityWithDialog.getPackageName().equals(packageName)) {
442 return false;
443 }
444 }
445
Mayank Gargfde5e662021-01-19 22:21:10 -0800446 if (searchFromClientPolicyBlocklistsLocked(packageName)) {
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800447 return false;
448 }
Mayank Gargfde5e662021-01-19 22:21:10 -0800449
450 if (isActivityInClientPolicyAllowlistsLocked(packageName, className)) {
451 return true;
452 }
453
454 // Check deny and allow list
455 boolean packageBlocked = mActivityDenylistPackages.contains(packageName);
456 AppBlockingPackageInfoWrapper infoWrapper = mActivityAllowlistMap.get(packageName);
457 if (!packageBlocked && infoWrapper == null) {
458 // Update cache
459 updateActivityAllowlistAndDenylistMap(packageName);
460 packageBlocked = mActivityDenylistPackages.contains(packageName);
461 infoWrapper = mActivityAllowlistMap.get(packageName);
462 }
463
464 if (packageBlocked
465 || !isActivityInMapAndMatching(infoWrapper, packageName, className)) {
466 return false;
467 }
468
469 return true;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800470 }
471 }
472
Mayank Garg771c7452021-03-09 13:33:26 -0800473 @VisibleForTesting
Mayank Garg892160e2021-03-22 22:43:23 -0700474 boolean callerCanQueryPackage(String packageName) {
Mayank Garg771c7452021-03-09 13:33:26 -0800475 int callingUid = Binder.getCallingUid();
476 if (hasPermissionGranted(QUERY_ALL_PACKAGES, callingUid)) {
Mayank Garg892160e2021-03-22 22:43:23 -0700477 return true;
Mayank Garg771c7452021-03-09 13:33:26 -0800478 }
479 String[] packages = mPackageManager.getPackagesForUid(callingUid);
480 if (packages != null && packages.length > 0) {
481 for (int i = 0; i < packages.length; i++) {
482 if (Objects.equals(packageName, packages[i])) {
Mayank Garg892160e2021-03-22 22:43:23 -0700483 return true;
Mayank Garg771c7452021-03-09 13:33:26 -0800484 }
485 }
486 }
487
Mayank Gargbfa66132021-05-05 19:56:20 -0700488 Slog.w(TAG, QUERY_ALL_PACKAGES + " permission is needed to query other packages.");
Mayank Garg892160e2021-03-22 22:43:23 -0700489
490 return false;
Mayank Garg771c7452021-03-09 13:33:26 -0800491 }
492
493 private static boolean hasPermissionGranted(String permission, int uid) {
494 return ActivityManager.checkComponentPermission(permission, uid,
495 /* owningUid= */ Process.INVALID_UID,
496 /* exported= */ true) == PackageManager.PERMISSION_GRANTED;
497 }
498
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800499 @Override
Arnaud Berryd1f88ee2020-02-19 13:49:31 -0800500 public boolean isPendingIntentDistractionOptimized(PendingIntent pendingIntent) {
501 ResolveInfo info = mPackageManager.resolveActivity(
502 pendingIntent.getIntent(), PackageManager.MATCH_DEFAULT_ONLY);
503 if (info == null) return false;
504 ActivityInfo activityInfo = info.activityInfo;
505 return isActivityDistractionOptimized(activityInfo.packageName, activityInfo.name);
506 }
507
508 @Override
Ram Periathiruvadie154f582018-03-21 21:53:27 -0700509 public boolean isServiceDistractionOptimized(String packageName, String className) {
Mayank Garg892160e2021-03-22 22:43:23 -0700510 if (!callerCanQueryPackage(packageName)) return false;
511
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800512 if (packageName == null) {
513 throw new IllegalArgumentException("Package name null");
514 }
Yan Zhu211b1fe2019-11-06 15:54:19 -0800515 synchronized (mLock) {
Mayank Gargbfa66132021-05-05 19:56:20 -0700516 if (Log.isLoggable(TAG, Log.DEBUG)) {
517 Slog.d(TAG, "isServiceDistractionOptimized" + dumpPoliciesLocked(false));
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800518 }
Mayank Gargfde5e662021-01-19 22:21:10 -0800519
520 if (searchFromClientPolicyBlocklistsLocked(packageName)) {
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800521 return false;
522 }
Mayank Gargfde5e662021-01-19 22:21:10 -0800523
524 if (searchFromClientPolicyAllowlistsLocked(packageName)) {
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800525 return true;
526 }
Mayank Gargfde5e662021-01-19 22:21:10 -0800527
528 // Check deny and allow list
529 boolean packageBlocked = mActivityDenylistPackages.contains(packageName);
530 AppBlockingPackageInfoWrapper infoWrapper = mActivityAllowlistMap.get(packageName);
531 if (!packageBlocked && infoWrapper == null) {
532 // Update cache
533 updateActivityAllowlistAndDenylistMap(packageName);
534 packageBlocked = mActivityDenylistPackages.contains(packageName);
535 infoWrapper = mActivityAllowlistMap.get(packageName);
536 }
537
538 if (packageBlocked || infoWrapper == null || infoWrapper.info == null) {
539 return false;
540 }
541
542 return true;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800543 }
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800544 }
545
Keun-young Park4727da32016-05-31 10:00:51 -0700546 @Override
547 public boolean isActivityBackedBySafeActivity(ComponentName activityName) {
Mayank Garg771c7452021-03-09 13:33:26 -0800548 if (activityName == null) return false;
Mayank Garg892160e2021-03-22 22:43:23 -0700549 if (!callerCanQueryPackage(activityName.getPackageName())) return false;
550
Louis Chang3bf2f202020-08-18 13:04:28 +0800551 RootTaskInfo info = mSystemActivityMonitoringService.getFocusedStackForTopActivity(
Keun-young Park4727da32016-05-31 10:00:51 -0700552 activityName);
553 if (info == null) { // not top in focused stack
554 return true;
555 }
Yao, Yuxingd525de12019-05-06 15:11:48 -0700556 if (!isUxRestrictedOnDisplay(info.displayId)) {
557 return true;
558 }
Louis Chang3bf2f202020-08-18 13:04:28 +0800559 if (info.childTaskNames.length <= 1) { // nothing below this.
Keun-young Park4727da32016-05-31 10:00:51 -0700560 return false;
561 }
562 ComponentName activityBehind = ComponentName.unflattenFromString(
Louis Chang3bf2f202020-08-18 13:04:28 +0800563 info.childTaskNames[info.childTaskNames.length - 2]);
Ram Periathiruvadie154f582018-03-21 21:53:27 -0700564 return isActivityDistractionOptimized(activityBehind.getPackageName(),
Keun-young Park4727da32016-05-31 10:00:51 -0700565 activityBehind.getClassName());
566 }
567
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800568 public Looper getLooper() {
569 return mHandlerThread.getLooper();
570 }
571
572 private void assertPackageAndClassName(String packageName, String className) {
573 if (packageName == null) {
574 throw new IllegalArgumentException("Package name null");
575 }
576 if (className == null) {
577 throw new IllegalArgumentException("Class name null");
578 }
579 }
580
Yan Zhu211b1fe2019-11-06 15:54:19 -0800581 @GuardedBy("mLock")
Mayank Gargfde5e662021-01-19 22:21:10 -0800582 private boolean searchFromClientPolicyBlocklistsLocked(String packageName) {
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800583 for (ClientPolicy policy : mClientPolicies.values()) {
Jordan Jozwiak794abcb2020-07-27 08:08:11 -0700584 AppBlockingPackageInfoWrapper wrapper = policy.mBlocklistsMap.get(packageName);
Mayank Gargfde5e662021-01-19 22:21:10 -0800585 if (wrapper != null && wrapper.isMatching && wrapper.info != null) {
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800586 return true;
587 }
588 }
Mayank Gargfde5e662021-01-19 22:21:10 -0800589
590 return false;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800591 }
592
Mayank Gargfde5e662021-01-19 22:21:10 -0800593 @GuardedBy("mLock")
594 private boolean searchFromClientPolicyAllowlistsLocked(String packageName) {
595 for (ClientPolicy policy : mClientPolicies.values()) {
596 AppBlockingPackageInfoWrapper wrapper = policy.mAllowlistsMap.get(packageName);
597 if (wrapper != null && wrapper.isMatching && wrapper.info != null) {
598 return true;
599 }
600 }
601 return false;
602 }
603
604 @GuardedBy("mLock")
605 private boolean isActivityInClientPolicyAllowlistsLocked(String packageName, String className) {
606 for (ClientPolicy policy : mClientPolicies.values()) {
607 if (isActivityInMapAndMatching(policy.mAllowlistsMap.get(packageName), packageName,
608 className)) {
609 return true;
610 }
611 }
612 return false;
613 }
614
615 private boolean isActivityInMapAndMatching(AppBlockingPackageInfoWrapper wrapper,
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800616 String packageName, String className) {
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800617 if (wrapper == null || !wrapper.isMatching) {
Mayank Gargbfa66132021-05-05 19:56:20 -0700618 if (Log.isLoggable(TAG, Log.DEBUG)) {
619 Slog.d(TAG, "Pkg not in allowlist:" + packageName);
Ram Periathiruvadi38388302018-02-22 16:42:49 -0800620 }
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800621 return false;
622 }
623 return wrapper.info.isActivityCovered(className);
624 }
625
626 @Override
627 public void init() {
Keun young Park40fcb0c2021-09-14 18:47:28 -0700628 String safetyRegion = SystemProperties.get(PROPERTY_RO_DRIVING_SAFETY_REGION, "");
Yan Zhu211b1fe2019-11-06 15:54:19 -0800629 synchronized (mLock) {
Keun young Park40fcb0c2021-09-14 18:47:28 -0700630 setDrivingSafetyRegionWithCheckLocked(safetyRegion);
Keun-young Park98960812016-10-04 12:50:54 -0700631 mHandler.requestInit();
Keun-young Park4727da32016-05-31 10:00:51 -0700632 }
Keun young Park40fcb0c2021-09-14 18:47:28 -0700633 CarLocalServices.getService(CarUserService.class).addUserLifecycleListener(
634 mUserLifecycleListener);
635 CarLocalServices.getService(CarPowerManagementService.class).addPowerPolicyListener(
636 new CarPowerPolicyFilter.Builder().setComponents(PowerComponent.DISPLAY).build(),
637 mDisplayPowerPolicyListener);
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800638 }
639
640 @Override
641 public void release() {
Keun young Park40fcb0c2021-09-14 18:47:28 -0700642 CarLocalServices.getService(CarPowerManagementService.class).removePowerPolicyListener(
643 mDisplayPowerPolicyListener);
644 CarLocalServices.getService(CarUserService.class).removeUserLifecycleListener(
645 mUserLifecycleListener);
Yan Zhu211b1fe2019-11-06 15:54:19 -0800646 synchronized (mLock) {
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800647 mHandler.requestRelease();
Keun-young Park6dcc50b2016-10-10 19:01:11 -0700648 // wait for release do be done. This guarantees that init is done.
649 try {
Yan Zhu211b1fe2019-11-06 15:54:19 -0800650 mLock.wait();
Keun-young Park6dcc50b2016-10-10 19:01:11 -0700651 } catch (InterruptedException e) {
Mayank Gargbfa66132021-05-05 19:56:20 -0700652 Slog.e(TAG, "Interrupted wait during release");
Yan Zhu211b1fe2019-11-06 15:54:19 -0800653 Thread.currentThread().interrupt();
Keun-young Park6dcc50b2016-10-10 19:01:11 -0700654 }
Jordan Jozwiak794abcb2020-07-27 08:08:11 -0700655 mActivityAllowlistMap.clear();
Mayank Gargfde5e662021-01-19 22:21:10 -0800656 mActivityDenylistPackages.clear();
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800657 mClientPolicies.clear();
658 if (mProxies != null) {
659 for (AppBlockingPolicyProxy proxy : mProxies) {
660 proxy.disconnect();
661 }
662 mProxies.clear();
663 }
Keun young Park6c4fd342019-12-13 12:46:04 -0800664 mWaitingPolicies.clear();
Keun young Park40fcb0c2021-09-14 18:47:28 -0700665 resetTempAllowedActivitiesLocked();
Keun young Parkff3196b2020-01-07 12:44:10 -0800666 mLock.notifyAll();
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800667 }
Ram Periathiruvadi295954d2018-04-10 18:27:28 -0700668 mContext.unregisterReceiver(mPackageParsingEventReceiver);
Keun-young Park98960812016-10-04 12:50:54 -0700669 mSystemActivityMonitoringService.registerActivityLaunchListener(null);
Yao, Yuxingd525de12019-05-06 15:11:48 -0700670 for (int i = 0; i < mUxRestrictionsListeners.size(); i++) {
671 UxRestrictionsListener listener = mUxRestrictionsListeners.valueAt(i);
672 mCarUxRestrictionsService.unregisterUxRestrictionsChangeListener(listener);
673 }
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800674 }
675
Keun young Park40fcb0c2021-09-14 18:47:28 -0700676 @GuardedBy("mLock")
677 private void setDrivingSafetyRegionWithCheckLocked(String region) {
678 if (region.isEmpty()) {
679 mCurrentDrivingSafetyRegion = CarPackageManager.DRIVING_SAFETY_REGION_ALL;
680 } else {
681 mCurrentDrivingSafetyRegion = region;
682 }
683 }
684
685 /**
686 * Reset driving stat and all dynamically added allow list so that region information for
687 * all packages are reset. This also resets one time allow list.
688 */
689 public void resetDrivingSafetyRegion(@NonNull String region) {
690 synchronized (mLock) {
691 setDrivingSafetyRegionWithCheckLocked(region);
692 resetTempAllowedActivitiesLocked();
693 mActivityAllowlistMap.clear();
694 mActivityDenylistPackages.clear();
695 }
696 }
697
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800698 // run from HandlerThread
699 private void doHandleInit() {
Ram Periathiruvadi295954d2018-04-10 18:27:28 -0700700 startAppBlockingPolicies();
701 IntentFilter pkgParseIntent = new IntentFilter();
Ram Periathiruvadi295954d2018-04-10 18:27:28 -0700702 for (String action : mPackageManagerActions) {
703 pkgParseIntent.addAction(action);
704 }
705 pkgParseIntent.addDataScheme("package");
Yao, Yuxing0c6fc732019-05-10 14:58:49 -0700706 mContext.registerReceiverAsUser(mPackageParsingEventReceiver, UserHandle.ALL,
707 pkgParseIntent, null, null);
Yao, Yuxingd525de12019-05-06 15:11:48 -0700708
709 List<Display> physicalDisplays = getPhysicalDisplays();
710
711 // Assume default display (display 0) is always a physical display.
712 Display defaultDisplay = mDisplayManager.getDisplay(Display.DEFAULT_DISPLAY);
713 if (!physicalDisplays.contains(defaultDisplay)) {
Mayank Gargbfa66132021-05-05 19:56:20 -0700714 if (Log.isLoggable(TAG, Log.INFO)) {
715 Slog.i(TAG, "Adding default display to physical displays.");
Yao, Yuxingd525de12019-05-06 15:11:48 -0700716 }
717 physicalDisplays.add(defaultDisplay);
718 }
719 for (Display physicalDisplay : physicalDisplays) {
720 int displayId = physicalDisplay.getDisplayId();
721 UxRestrictionsListener listener = new UxRestrictionsListener(mCarUxRestrictionsService);
722 mUxRestrictionsListeners.put(displayId, listener);
723 mCarUxRestrictionsService.registerUxRestrictionsChangeListener(listener, displayId);
Keun-young Park6dcc50b2016-10-10 19:01:11 -0700724 }
Pavel Maltsev38da4312019-04-08 10:38:38 -0700725 mVendorServiceController.init();
Mayank Gargfde5e662021-01-19 22:21:10 -0800726 mSystemActivityMonitoringService.registerActivityLaunchListener(mActivityLaunchListener);
Ram Periathiruvadi38388302018-02-22 16:42:49 -0800727 }
728
Mayank Gargfde5e662021-01-19 22:21:10 -0800729 private void doParseInstalledPackage(String packageName) {
730 // Delete the package from allowlist and denylist mapping
Yan Zhu211b1fe2019-11-06 15:54:19 -0800731 synchronized (mLock) {
Mayank Gargfde5e662021-01-19 22:21:10 -0800732 mActivityDenylistPackages.remove(packageName);
733 mActivityAllowlistMap.remove(packageName);
Ram Periathiruvadic57678d2018-04-23 09:18:33 -0700734 }
Mayank Gargfde5e662021-01-19 22:21:10 -0800735
736 // Generate allowlist and denylist mapping for the package
737 updateActivityAllowlistAndDenylistMap(packageName);
Yao, Yuxingd525de12019-05-06 15:11:48 -0700738 blockTopActivitiesIfNecessary();
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800739 }
740
Yan Zhu211b1fe2019-11-06 15:54:19 -0800741 private void doHandleRelease() {
742 synchronized (mLock) {
743 mVendorServiceController.release();
744 mLock.notifyAll();
745 }
Keun-young Park6dcc50b2016-10-10 19:01:11 -0700746 }
747
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800748 private void doUpdatePolicy(String packageName, CarAppBlockingPolicy policy, int flags) {
Mayank Gargbfa66132021-05-05 19:56:20 -0700749 if (Log.isLoggable(TAG, Log.DEBUG)) {
750 Slog.d(TAG, "setting policy from:" + packageName + ",policy:" + policy + ",flags:0x"
751 + Integer.toHexString(flags));
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800752 }
Jordan Jozwiak794abcb2020-07-27 08:08:11 -0700753 AppBlockingPackageInfoWrapper[] blocklistWrapper = verifyList(policy.blacklists);
754 AppBlockingPackageInfoWrapper[] allowlistWrapper = verifyList(policy.whitelists);
Yan Zhu211b1fe2019-11-06 15:54:19 -0800755 synchronized (mLock) {
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800756 ClientPolicy clientPolicy = mClientPolicies.get(packageName);
757 if (clientPolicy == null) {
758 clientPolicy = new ClientPolicy();
759 mClientPolicies.put(packageName, clientPolicy);
760 }
761 if ((flags & CarPackageManager.FLAG_SET_POLICY_ADD) != 0) {
Jordan Jozwiak794abcb2020-07-27 08:08:11 -0700762 clientPolicy.addToBlocklists(blocklistWrapper);
763 clientPolicy.addToAllowlists(allowlistWrapper);
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800764 } else if ((flags & CarPackageManager.FLAG_SET_POLICY_REMOVE) != 0) {
Jordan Jozwiak794abcb2020-07-27 08:08:11 -0700765 clientPolicy.removeBlocklists(blocklistWrapper);
766 clientPolicy.removeAllowlists(allowlistWrapper);
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800767 } else { //replace.
Jordan Jozwiak794abcb2020-07-27 08:08:11 -0700768 clientPolicy.replaceBlocklists(blocklistWrapper);
769 clientPolicy.replaceAllowlists(allowlistWrapper);
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800770 }
771 if ((flags & CarPackageManager.FLAG_SET_POLICY_WAIT_FOR_CHANGE) != 0) {
Keun young Park6c4fd342019-12-13 12:46:04 -0800772 mWaitingPolicies.remove(policy);
Keun young Parkff3196b2020-01-07 12:44:10 -0800773 mLock.notifyAll();
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800774 }
Mayank Gargbfa66132021-05-05 19:56:20 -0700775 if (Log.isLoggable(TAG, Log.DEBUG)) {
776 Slog.d(TAG, "policy set:" + dumpPoliciesLocked(false));
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800777 }
778 }
Keun-young Park4727da32016-05-31 10:00:51 -0700779 blockTopActivitiesIfNecessary();
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800780 }
781
782 private AppBlockingPackageInfoWrapper[] verifyList(AppBlockingPackageInfo[] list) {
783 if (list == null) {
784 return null;
785 }
786 LinkedList<AppBlockingPackageInfoWrapper> wrappers = new LinkedList<>();
787 for (int i = 0; i < list.length; i++) {
788 AppBlockingPackageInfo info = list[i];
789 if (info == null) {
790 continue;
791 }
792 boolean isMatching = isInstalledPackageMatching(info);
793 wrappers.add(new AppBlockingPackageInfoWrapper(info, isMatching));
794 }
795 return wrappers.toArray(new AppBlockingPackageInfoWrapper[wrappers.size()]);
796 }
797
798 boolean isInstalledPackageMatching(AppBlockingPackageInfo info) {
Yao, Yuxing4ddb2c62019-02-04 11:26:46 -0800799 PackageInfo packageInfo;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800800 try {
801 packageInfo = mPackageManager.getPackageInfo(info.packageName,
802 PackageManager.GET_SIGNATURES);
803 } catch (NameNotFoundException e) {
804 return false;
805 }
806 if (packageInfo == null) {
807 return false;
808 }
809 // if it is system app and client specified the flag, do not check signature
810 if ((info.flags & AppBlockingPackageInfo.FLAG_SYSTEM_APP) == 0 ||
811 (!packageInfo.applicationInfo.isSystemApp() &&
812 !packageInfo.applicationInfo.isUpdatedSystemApp())) {
Yao, Yuxing4ddb2c62019-02-04 11:26:46 -0800813 Signature[] signatures = packageInfo.signatures;
814 if (!isAnySignatureMatching(signatures, info.signatures)) {
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800815 return false;
816 }
817 }
818 int version = packageInfo.versionCode;
819 if (info.minRevisionCode == 0) {
820 if (info.maxRevisionCode == 0) { // all versions
821 return true;
822 } else { // only max version matters
823 return info.maxRevisionCode > version;
824 }
825 } else { // min version matters
826 if (info.maxRevisionCode == 0) {
827 return info.minRevisionCode < version;
828 } else {
829 return (info.minRevisionCode < version) && (info.maxRevisionCode > version);
830 }
831 }
832 }
833
834 /**
835 * Any signature from policy matching with package's signatures is treated as matching.
836 */
837 boolean isAnySignatureMatching(Signature[] fromPackage, Signature[] fromPolicy) {
838 if (fromPackage == null) {
839 return false;
840 }
841 if (fromPolicy == null) {
842 return false;
843 }
844 ArraySet<Signature> setFromPackage = new ArraySet<Signature>();
845 for (Signature sig : fromPackage) {
846 setFromPackage.add(sig);
847 }
848 for (Signature sig : fromPolicy) {
849 if (setFromPackage.contains(sig)) {
850 return true;
851 }
852 }
853 return false;
854 }
855
Mayank Gargfde5e662021-01-19 22:21:10 -0800856 private AppBlockingPackageInfoWrapper getPackageInfoWrapperForUser(String packageName,
857 @UserIdInt int userId, Map<String, Set<String>> configAllowlist,
858 Map<String, Set<String>> configBlocklist) {
859 PackageInfo info;
860 try {
861 info = mPackageManager.getPackageInfoAsUser(packageName,
862 PackageManager.GET_SIGNATURES | PackageManager.GET_ACTIVITIES
863 | PackageManager.MATCH_DIRECT_BOOT_AWARE
864 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
865 | PackageManager.MATCH_DISABLED_COMPONENTS,
866 userId);
867 } catch (NameNotFoundException e) {
Mayank Gargbfa66132021-05-05 19:56:20 -0700868 Slog.w(TAG, packageName + " not installed! User Id: " + userId);
Mayank Gargfde5e662021-01-19 22:21:10 -0800869 return null;
870 }
871
872
873 if (info == null || info.applicationInfo == null) {
874 return null;
875 }
876
877 int flags = 0;
878 Set<String> activities = new ArraySet<>();
879
880 if (info.applicationInfo.isSystemApp()
881 || info.applicationInfo.isUpdatedSystemApp()) {
882 flags = AppBlockingPackageInfo.FLAG_SYSTEM_APP;
883 }
884
885 /* 1. Check if all or some of this app is in the <activityAllowlist> or
886 <systemActivityAllowlist> in config.xml */
887 Set<String> configActivitiesForPackage = configAllowlist.get(info.packageName);
888 if (configActivitiesForPackage != null) {
Mayank Gargbfa66132021-05-05 19:56:20 -0700889 if (Log.isLoggable(TAG, Log.DEBUG)) {
890 Slog.d(TAG, info.packageName + " allowlisted");
Mayank Gargfde5e662021-01-19 22:21:10 -0800891 }
Mayank Gargbfa66132021-05-05 19:56:20 -0700892
Mayank Gargfde5e662021-01-19 22:21:10 -0800893 if (configActivitiesForPackage.isEmpty()) {
894 // Whole Pkg has been allowlisted
895 flags |= AppBlockingPackageInfo.FLAG_WHOLE_ACTIVITY;
896 // Add all activities to the allowlist
897 List<String> activitiesForPackage = getActivitiesInPackage(info);
898 if (activitiesForPackage != null) {
899 activities.addAll(activitiesForPackage);
900 } else {
Mayank Gargbfa66132021-05-05 19:56:20 -0700901 if (Log.isLoggable(TAG, Log.DEBUG)) {
902 Slog.d(TAG, info.packageName + ": Activities null");
Mayank Gargfde5e662021-01-19 22:21:10 -0800903 }
904 }
905 } else {
Mayank Gargbfa66132021-05-05 19:56:20 -0700906 if (Log.isLoggable(TAG, Log.DEBUG)) {
907 Slog.d(TAG, "Partially Allowlisted. WL Activities: "
908 + configActivitiesForPackage);
Mayank Gargfde5e662021-01-19 22:21:10 -0800909 }
910 activities.addAll(configActivitiesForPackage);
911 }
912 }
913 /* 2. If app is not listed in the config.xml check their Manifest meta-data to
914 see if they have any Distraction Optimized(DO) activities.
915 For non system apps, we check if the app install source was a permittable
916 source. This prevents side-loaded apps to fake DO. Bypass the check
917 for debug builds for development convenience. */
918 if (!isDebugBuild()
919 && !info.applicationInfo.isSystemApp()
920 && !info.applicationInfo.isUpdatedSystemApp()) {
921 try {
922 if (mAllowedAppInstallSources != null) {
923 String installerName = mPackageManager.getInstallerPackageName(
924 info.packageName);
925 if (installerName == null || (installerName != null
926 && !mAllowedAppInstallSources.contains(installerName))) {
Mayank Gargbfa66132021-05-05 19:56:20 -0700927 Slog.w(TAG,
Mayank Gargfde5e662021-01-19 22:21:10 -0800928 info.packageName + " not installed from permitted sources "
929 + (installerName == null ? "NULL" : installerName));
930 return null;
931 }
932 }
933 } catch (IllegalArgumentException e) {
Mayank Gargbfa66132021-05-05 19:56:20 -0700934 Slog.w(TAG, info.packageName + " not installed!");
Mayank Gargfde5e662021-01-19 22:21:10 -0800935 return null;
936 }
937 }
938
939 try {
Keun young Park40fcb0c2021-09-14 18:47:28 -0700940 String[] doActivities = findDistractionOptimizedActivitiesAsUser(info.packageName,
941 userId);
Mayank Gargfde5e662021-01-19 22:21:10 -0800942 if (doActivities != null) {
943 // Some of the activities in this app are Distraction Optimized.
Mayank Gargbfa66132021-05-05 19:56:20 -0700944 if (Log.isLoggable(TAG, Log.DEBUG)) {
Mayank Gargfde5e662021-01-19 22:21:10 -0800945 for (String activity : doActivities) {
Mayank Gargbfa66132021-05-05 19:56:20 -0700946 Slog.d(TAG, "adding " + activity + " from " + info.packageName
947 + " to allowlist");
Mayank Gargfde5e662021-01-19 22:21:10 -0800948 }
949 }
Mayank Gargbfa66132021-05-05 19:56:20 -0700950
Mayank Gargfde5e662021-01-19 22:21:10 -0800951 activities.addAll(Arrays.asList(doActivities));
952 }
953 } catch (NameNotFoundException e) {
Mayank Gargbfa66132021-05-05 19:56:20 -0700954 Slog.w(TAG, "Error reading metadata: " + info.packageName);
Mayank Gargfde5e662021-01-19 22:21:10 -0800955 return null;
956 }
957
958 // Nothing to add to allowlist
959 if (activities.isEmpty()) {
960 return null;
961 }
962
963 /* 3. Check if parsed activity is in <activityBlocklist> in config.xml. Anything
964 in blocklist should not be allowlisted, either as D.O. or by config. */
965 if (configBlocklist.containsKey(info.packageName)) {
966 Set<String> configBlocklistActivities = configBlocklist.get(info.packageName);
967 if (configBlocklistActivities.isEmpty()) {
968 // Whole package should be blocklisted.
969 return null;
970 }
971 activities.removeAll(configBlocklistActivities);
972 }
973
974 Signature[] signatures;
975 signatures = info.signatures;
976 AppBlockingPackageInfo appBlockingInfo = new AppBlockingPackageInfo(info.packageName,
977 /* minRevisionCode = */ 0, /* maxRevisionCode = */ 0, flags, signatures,
978 activities.toArray(new String[activities.size()]));
979 AppBlockingPackageInfoWrapper wrapper = new AppBlockingPackageInfoWrapper(
980 appBlockingInfo, true);
981 return wrapper;
982 }
983
Keun-young Park4727da32016-05-31 10:00:51 -0700984 /**
Mayank Gargfde5e662021-01-19 22:21:10 -0800985 * Update map of allowlisted packages and activities of the form {pkgName, Allowlisted
986 * activities} and set of denylisted packages. The information can come from a configuration XML
987 * resource or from the apps marking their activities as distraction optimized.
Keun-young Park4727da32016-05-31 10:00:51 -0700988 */
Mayank Gargfde5e662021-01-19 22:21:10 -0800989 private void updateActivityAllowlistAndDenylistMap(String packageName) {
990 int userId = mActivityManager.getCurrentUser();
Mayank Gargbfa66132021-05-05 19:56:20 -0700991 Slog.d(TAG, "Updating allowlist and denylist mapping for package: " + packageName
992 + " for UserId: " + userId);
Jordan Jozwiak794abcb2020-07-27 08:08:11 -0700993 // Get the apps/activities that are allowlisted in the configuration XML resources.
994 Map<String, Set<String>> configAllowlist = generateConfigAllowlist();
995 Map<String, Set<String>> configBlocklist = generateConfigBlocklist();
Yao, Yuxing0c6fc732019-05-10 14:58:49 -0700996
Mayank Gargfde5e662021-01-19 22:21:10 -0800997 AppBlockingPackageInfoWrapper wrapper =
998 getPackageInfoWrapperForUser(packageName, userId, configAllowlist, configBlocklist);
999
1000 if (wrapper == null && userId != UserHandle.USER_SYSTEM) {
Mayank Gargbfa66132021-05-05 19:56:20 -07001001 Slog.d(TAG, "Updating allowlist and denylist mapping for package: " + packageName
1002 + " for UserId: " + UserHandle.USER_SYSTEM);
Mayank Gargfde5e662021-01-19 22:21:10 -08001003 // check package for system user, in case package is disabled for current user
1004 wrapper = getPackageInfoWrapperForUser(packageName, UserHandle.USER_SYSTEM,
1005 configAllowlist, configBlocklist);
Yao, Yuxing0c6fc732019-05-10 14:58:49 -07001006 }
Mayank Gargfde5e662021-01-19 22:21:10 -08001007
Yan Zhu211b1fe2019-11-06 15:54:19 -08001008 synchronized (mLock) {
Mayank Gargfde5e662021-01-19 22:21:10 -08001009 if (wrapper != null) {
Keun young Park40fcb0c2021-09-14 18:47:28 -07001010 if (DBG) {
1011 Slog.d(TAG, "Package: " + packageName + " added in allowlist.");
1012 }
Mayank Gargfde5e662021-01-19 22:21:10 -08001013 mActivityAllowlistMap.put(packageName, wrapper);
1014 } else {
Keun young Park40fcb0c2021-09-14 18:47:28 -07001015 if (DBG) {
1016 Slog.d(TAG, "Package: " + packageName + " added in denylist.");
1017 }
Mayank Gargfde5e662021-01-19 22:21:10 -08001018 mActivityDenylistPackages.add(packageName);
1019 }
Yao, Yuxing0c6fc732019-05-10 14:58:49 -07001020 }
1021 }
1022
Jordan Jozwiak794abcb2020-07-27 08:08:11 -07001023 private Map<String, Set<String>> generateConfigAllowlist() {
Mayank Gargfde5e662021-01-19 22:21:10 -08001024 synchronized (mLock) {
1025 if (mConfiguredAllowlistMap != null) return mConfiguredAllowlistMap;
1026
1027 Map<String, Set<String>> configAllowlist = new HashMap<>();
1028 mConfiguredAllowlist = mContext.getString(R.string.activityAllowlist);
1029 if (mConfiguredAllowlist == null) {
Mayank Gargbfa66132021-05-05 19:56:20 -07001030 Slog.w(TAG, "Allowlist is null.");
Ram Periathiruvadie6e2ac32018-05-02 14:57:46 -07001031 }
Mayank Gargfde5e662021-01-19 22:21:10 -08001032 parseConfigList(mConfiguredAllowlist, configAllowlist);
Yao, Yuxing0c6fc732019-05-10 14:58:49 -07001033
Mayank Gargfde5e662021-01-19 22:21:10 -08001034 mConfiguredSystemAllowlist = mContext.getString(R.string.systemActivityAllowlist);
1035 if (mConfiguredSystemAllowlist == null) {
Mayank Gargbfa66132021-05-05 19:56:20 -07001036 Slog.w(TAG, "System allowlist is null.");
Yao, Yuxing4c3b93c2019-02-20 09:00:01 -08001037 }
Mayank Gargfde5e662021-01-19 22:21:10 -08001038 parseConfigList(mConfiguredSystemAllowlist, configAllowlist);
Yao, Yuxing4c3b93c2019-02-20 09:00:01 -08001039
Mayank Gargfde5e662021-01-19 22:21:10 -08001040 // Add the blocking overlay activity to the allowlist, since that needs to run in a
1041 // restricted state to communicate the reason an app was blocked.
1042 Set<String> defaultActivity = new ArraySet<>();
1043 if (mActivityBlockingActivity != null) {
1044 defaultActivity.add(mActivityBlockingActivity.getClassName());
1045 configAllowlist.put(mActivityBlockingActivity.getPackageName(), defaultActivity);
1046 }
Ram Periathiruvadi38388302018-02-22 16:42:49 -08001047
Mayank Gargfde5e662021-01-19 22:21:10 -08001048 mConfiguredAllowlistMap = configAllowlist;
1049 return configAllowlist;
1050 }
Yao, Yuxing0c6fc732019-05-10 14:58:49 -07001051 }
1052
Jordan Jozwiak794abcb2020-07-27 08:08:11 -07001053 private Map<String, Set<String>> generateConfigBlocklist() {
Mayank Gargfde5e662021-01-19 22:21:10 -08001054 synchronized (mLock) {
1055 if (mConfiguredBlocklistMap != null) return mConfiguredBlocklistMap;
Yao, Yuxing0c6fc732019-05-10 14:58:49 -07001056
Mayank Gargfde5e662021-01-19 22:21:10 -08001057 Map<String, Set<String>> configBlocklist = new HashMap<>();
1058 mConfiguredBlocklist = mContext.getString(R.string.activityDenylist);
1059 if (mConfiguredBlocklist == null) {
Mayank Gargbfa66132021-05-05 19:56:20 -07001060 if (Log.isLoggable(TAG, Log.DEBUG)) {
1061 Slog.d(TAG, "Null blocklist in config");
Ram Periathiruvadi38388302018-02-22 16:42:49 -08001062 }
Yao, Yuxing2a1e1d92019-01-08 11:58:52 -08001063 }
Mayank Gargfde5e662021-01-19 22:21:10 -08001064 parseConfigList(mConfiguredBlocklist, configBlocklist);
Yao, Yuxing2a1e1d92019-01-08 11:58:52 -08001065
Mayank Gargfde5e662021-01-19 22:21:10 -08001066 mConfiguredBlocklistMap = configBlocklist;
1067 return configBlocklist;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001068 }
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001069 }
1070
Ram Periathiruvadid937c322018-06-13 12:28:12 -07001071 private boolean isDebugBuild() {
1072 return Build.IS_USERDEBUG || Build.IS_ENG;
1073 }
1074
Ram Periathiruvadi46a3a3d2018-03-23 16:58:32 -07001075 /**
Yao, Yuxing4c3b93c2019-02-20 09:00:01 -08001076 * Parses the given resource and updates the input map of packages and activities.
1077 *
1078 * Key is package name and value is list of activities. Empty set implies whole package is
Ram Periathiruvadi46a3a3d2018-03-23 16:58:32 -07001079 * included.
Yao, Yuxing4c3b93c2019-02-20 09:00:01 -08001080 *
1081 * When there are multiple entries regarding one package, the entry with
Jordan Jozwiak794abcb2020-07-27 08:08:11 -07001082 * greater scope wins. Namely if there were 2 entries such that one allowlists
1083 * an activity, and the other allowlists the entire package of the activity,
1084 * the package is allowlisted, regardless of input order.
Ram Periathiruvadi46a3a3d2018-03-23 16:58:32 -07001085 */
Yao, Yuxing4c3b93c2019-02-20 09:00:01 -08001086 @VisibleForTesting
1087 /* package */ void parseConfigList(String configList,
1088 @NonNull Map<String, Set<String>> packageToActivityMap) {
Ram Periathiruvadie6e2ac32018-05-02 14:57:46 -07001089 if (configList == null) {
Yao, Yuxing4c3b93c2019-02-20 09:00:01 -08001090 return;
Ram Periathiruvadie6e2ac32018-05-02 14:57:46 -07001091 }
Ram Periathiruvadi46a3a3d2018-03-23 16:58:32 -07001092 String[] entries = configList.split(PACKAGE_DELIMITER);
1093 for (String entry : entries) {
1094 String[] packageActivityPair = entry.split(PACKAGE_ACTIVITY_DELIMITER);
1095 Set<String> activities = packageToActivityMap.get(packageActivityPair[0]);
1096 boolean newPackage = false;
1097 if (activities == null) {
1098 activities = new ArraySet<>();
1099 newPackage = true;
1100 packageToActivityMap.put(packageActivityPair[0], activities);
1101 }
1102 if (packageActivityPair.length == 1) { // whole package
1103 activities.clear();
1104 } else if (packageActivityPair.length == 2) {
Jordan Jozwiak794abcb2020-07-27 08:08:11 -07001105 // add class name only when the whole package is not allowlisted.
Ram Periathiruvadi46a3a3d2018-03-23 16:58:32 -07001106 if (newPackage || (activities.size() > 0)) {
1107 activities.add(packageActivityPair[1]);
1108 }
1109 }
1110 }
Ram Periathiruvadi46a3a3d2018-03-23 16:58:32 -07001111 }
1112
Ram Periathiruvadi38388302018-02-22 16:42:49 -08001113 @Nullable
Yao, Yuxing2a1e1d92019-01-08 11:58:52 -08001114 private List<String> getActivitiesInPackage(PackageInfo info) {
Ram Periathiruvadi38388302018-02-22 16:42:49 -08001115 if (info == null || info.activities == null) {
1116 return null;
1117 }
1118 List<String> activityList = new ArrayList<>();
1119 for (ActivityInfo aInfo : info.activities) {
1120 activityList.add(aInfo.name);
1121 }
Yao, Yuxing2a1e1d92019-01-08 11:58:52 -08001122 return activityList;
Ram Periathiruvadi38388302018-02-22 16:42:49 -08001123 }
1124
Ram Periathiruvadi8ef1a202018-03-16 17:49:21 -07001125 /**
1126 * Checks if there are any {@link CarAppBlockingPolicyService} and creates a proxy to
1127 * bind to them and retrieve the {@link CarAppBlockingPolicy}
1128 */
1129 @VisibleForTesting
1130 public void startAppBlockingPolicies() {
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001131 Intent policyIntent = new Intent();
1132 policyIntent.setAction(CarAppBlockingPolicyService.SERVICE_INTERFACE);
1133 List<ResolveInfo> policyInfos = mPackageManager.queryIntentServices(policyIntent, 0);
1134 if (policyInfos == null) { //no need to wait for service binding and retrieval.
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001135 return;
1136 }
1137 LinkedList<AppBlockingPolicyProxy> proxies = new LinkedList<>();
1138 for (ResolveInfo resolveInfo : policyInfos) {
1139 ServiceInfo serviceInfo = resolveInfo.serviceInfo;
1140 if (serviceInfo == null) {
1141 continue;
1142 }
1143 if (serviceInfo.isEnabled()) {
1144 if (mPackageManager.checkPermission(Car.PERMISSION_CONTROL_APP_BLOCKING,
1145 serviceInfo.packageName) != PackageManager.PERMISSION_GRANTED) {
1146 continue;
1147 }
Mayank Gargbfa66132021-05-05 19:56:20 -07001148 Slog.i(TAG, "found policy holding service:" + serviceInfo);
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001149 AppBlockingPolicyProxy proxy = new AppBlockingPolicyProxy(this, mContext,
1150 serviceInfo);
1151 proxy.connect();
1152 proxies.add(proxy);
1153 }
1154 }
Yan Zhu211b1fe2019-11-06 15:54:19 -08001155 synchronized (mLock) {
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001156 mProxies = proxies;
1157 }
1158 }
1159
1160 public void onPolicyConnectionAndSet(AppBlockingPolicyProxy proxy,
1161 CarAppBlockingPolicy policy) {
1162 doHandlePolicyConnection(proxy, policy);
1163 }
1164
1165 public void onPolicyConnectionFailure(AppBlockingPolicyProxy proxy) {
1166 doHandlePolicyConnection(proxy, null);
1167 }
1168
1169 private void doHandlePolicyConnection(AppBlockingPolicyProxy proxy,
1170 CarAppBlockingPolicy policy) {
Yan Zhu211b1fe2019-11-06 15:54:19 -08001171 synchronized (mLock) {
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001172 if (mProxies == null) {
1173 proxy.disconnect();
1174 return;
1175 }
1176 mProxies.remove(proxy);
1177 if (mProxies.size() == 0) {
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001178 mProxies = null;
1179 }
1180 }
1181 try {
1182 if (policy != null) {
Mayank Gargbfa66132021-05-05 19:56:20 -07001183 if (Log.isLoggable(TAG, Log.DEBUG)) {
1184 Slog.d(TAG, "policy setting from policy service:" + proxy.getPackageName());
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001185 }
Keun young Park6c4fd342019-12-13 12:46:04 -08001186 doSetAppBlockingPolicy(proxy.getPackageName(), policy, 0);
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001187 }
1188 } finally {
1189 proxy.disconnect();
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001190 }
1191 }
1192
1193 @Override
Felipe Leme176a5fd2021-01-20 15:48:33 -08001194 public void dump(IndentingPrintWriter writer) {
Yan Zhu211b1fe2019-11-06 15:54:19 -08001195 synchronized (mLock) {
Jordan Jozwiak0aa05982019-06-17 15:14:39 -07001196 writer.println("*CarPackageManagerService*");
Keun-young Park4727da32016-05-31 10:00:51 -07001197 writer.println("mEnableActivityBlocking:" + mEnableActivityBlocking);
Keun young Park40fcb0c2021-09-14 18:47:28 -07001198 writer.println("mPreventTemplatedAppsFromShowingDialog:"
Gaurav Bholaafd79ef2021-06-16 13:22:03 +00001199 + mPreventTemplatedAppsFromShowingDialog);
Keun young Park40fcb0c2021-09-14 18:47:28 -07001200 writer.println("mTemplateActivityClassName:" + mTemplateActivityClassName);
Yao, Yuxingd525de12019-05-06 15:11:48 -07001201 List<String> restrictions = new ArrayList<>(mUxRestrictionsListeners.size());
1202 for (int i = 0; i < mUxRestrictionsListeners.size(); i++) {
1203 int displayId = mUxRestrictionsListeners.keyAt(i);
1204 UxRestrictionsListener listener = mUxRestrictionsListeners.valueAt(i);
1205 restrictions.add(String.format("Display %d is %s",
1206 displayId, (listener.isRestricted() ? "restricted" : "unrestricted")));
1207 }
1208 writer.println("Display Restrictions:\n" + String.join("\n", restrictions));
Jordan Jozwiak0aa05982019-06-17 15:14:39 -07001209 writer.println(" Blocked activity log:");
Bin Tan2536d402021-02-10 15:28:35 -08001210 mBlockedActivityLogs.dump(writer);
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001211 writer.print(dumpPoliciesLocked(true));
Keun young Park40fcb0c2021-09-14 18:47:28 -07001212 writer.print("mCurrentDrivingSafetyRegion:");
1213 writer.println(mCurrentDrivingSafetyRegion);
1214 writer.print("mTempAllowedActivities:");
1215 writer.println(mTempAllowedActivities);
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001216 }
1217 }
1218
Yan Zhu211b1fe2019-11-06 15:54:19 -08001219 @GuardedBy("mLock")
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001220 private String dumpPoliciesLocked(boolean dumpAll) {
1221 StringBuilder sb = new StringBuilder();
1222 if (dumpAll) {
Jordan Jozwiak794abcb2020-07-27 08:08:11 -07001223 sb.append("**System allowlist**\n");
1224 for (AppBlockingPackageInfoWrapper wrapper : mActivityAllowlistMap.values()) {
Ram Periathiruvadi46a3a3d2018-03-23 16:58:32 -07001225 sb.append(wrapper.toString() + "\n");
1226 }
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001227 }
1228 sb.append("**Client Policies**\n");
1229 for (Entry<String, ClientPolicy> entry : mClientPolicies.entrySet()) {
1230 sb.append("Client:" + entry.getKey() + "\n");
Jordan Jozwiak794abcb2020-07-27 08:08:11 -07001231 sb.append(" allowlists:\n");
1232 for (AppBlockingPackageInfoWrapper wrapper : entry.getValue().mAllowlistsMap.values()) {
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001233 sb.append(wrapper.toString() + "\n");
1234 }
Jordan Jozwiak794abcb2020-07-27 08:08:11 -07001235 sb.append(" blocklists:\n");
1236 for (AppBlockingPackageInfoWrapper wrapper : entry.getValue().mBlocklistsMap.values()) {
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001237 sb.append(wrapper.toString() + "\n");
1238 }
1239 }
1240 sb.append("**Unprocessed policy services**\n");
1241 if (mProxies != null) {
1242 for (AppBlockingPolicyProxy proxy : mProxies) {
1243 sb.append(proxy.toString() + "\n");
1244 }
1245 }
Jordan Jozwiak794abcb2020-07-27 08:08:11 -07001246 sb.append("**Allowlist string in resource**\n");
1247 sb.append(mConfiguredAllowlist + "\n");
Ram Periathiruvadi46a3a3d2018-03-23 16:58:32 -07001248
Jordan Jozwiak794abcb2020-07-27 08:08:11 -07001249 sb.append("**System allowlist string in resource**\n");
1250 sb.append(mConfiguredSystemAllowlist + "\n");
Yao, Yuxing0c6fc732019-05-10 14:58:49 -07001251
Jordan Jozwiak794abcb2020-07-27 08:08:11 -07001252 sb.append("**Blocklist string in resource**\n");
1253 sb.append(mConfiguredBlocklist + "\n");
Keun-young Park98960812016-10-04 12:50:54 -07001254
Mayank Gargfde5e662021-01-19 22:21:10 -08001255 sb.append("**Allowlist map from resource**\n");
1256 sb.append(mConfiguredAllowlistMap + "\n");
1257
1258 sb.append("**Blocklist from resource**\n");
1259 sb.append(mConfiguredBlocklist + "\n");
1260
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001261 return sb.toString();
1262 }
1263
Yao, Yuxingd525de12019-05-06 15:11:48 -07001264 /**
1265 * Returns display with physical address.
1266 */
1267 private List<Display> getPhysicalDisplays() {
1268 List<Display> displays = new ArrayList<>();
1269 for (Display display : mDisplayManager.getDisplays()) {
1270 if (display.getAddress() instanceof DisplayAddress.Physical) {
1271 displays.add(display);
1272 }
1273 }
1274 return displays;
1275 }
1276
1277 /**
1278 * Returns whether UX restrictions is required for display.
1279 *
1280 * Non-physical display will use restrictions for {@link Display#DEFAULT_DISPLAY}.
1281 */
1282 private boolean isUxRestrictedOnDisplay(int displayId) {
1283 UxRestrictionsListener listenerForTopTaskDisplay;
1284 if (mUxRestrictionsListeners.indexOfKey(displayId) < 0) {
1285 listenerForTopTaskDisplay = mUxRestrictionsListeners.get(Display.DEFAULT_DISPLAY);
1286 if (listenerForTopTaskDisplay == null) {
1287 // This should never happen.
Mayank Gargbfa66132021-05-05 19:56:20 -07001288 Slog.e(TAG, "Missing listener for default display.");
Yao, Yuxingd525de12019-05-06 15:11:48 -07001289 return true;
1290 }
1291 } else {
1292 listenerForTopTaskDisplay = mUxRestrictionsListeners.get(displayId);
1293 }
1294
1295 return listenerForTopTaskDisplay.isRestricted();
1296 }
1297
1298 private void blockTopActivitiesIfNecessary() {
1299 List<TopTaskInfoContainer> topTasks = mSystemActivityMonitoringService.getTopTasks();
1300 for (TopTaskInfoContainer topTask : topTasks) {
1301 if (topTask == null) {
Mayank Gargbfa66132021-05-05 19:56:20 -07001302 Slog.e(TAG, "Top tasks contains null.");
Yao, Yuxingd525de12019-05-06 15:11:48 -07001303 continue;
1304 }
1305 blockTopActivityIfNecessary(topTask);
1306 }
1307 }
1308
Keun-young Park4727da32016-05-31 10:00:51 -07001309 private void blockTopActivityIfNecessary(TopTaskInfoContainer topTask) {
Gaurav Bhola83173042021-06-21 09:36:20 +00001310 synchronized (mLock) {
Gaurav Bhola3a91fef2021-10-02 00:32:33 +00001311 if (!topTask.topActivity.equals(mActivityBlockingActivity)
1312 && mTopActivityWithDialogPerDisplay.contains(topTask.displayId)
Gaurav Bhola83173042021-06-21 09:36:20 +00001313 && !topTask.topActivity.equals(
1314 mTopActivityWithDialogPerDisplay.get(topTask.displayId))) {
1315 // Clear top activity-with-dialog if the activity has changed on this display.
1316 mTopActivityWithDialogPerDisplay.remove(topTask.displayId);
1317 }
1318 }
Yao, Yuxingd525de12019-05-06 15:11:48 -07001319 if (isUxRestrictedOnDisplay(topTask.displayId)) {
1320 doBlockTopActivityIfNotAllowed(topTask);
Yao, Yuxingcfcc59f2019-03-05 16:35:47 -08001321 }
Keun-young Park4727da32016-05-31 10:00:51 -07001322 }
1323
1324 private void doBlockTopActivityIfNotAllowed(TopTaskInfoContainer topTask) {
Ram Periathiruvadi2da6d0e2018-01-26 18:02:10 -08001325 if (topTask.topActivity == null) {
1326 return;
1327 }
Gaurav Bhola83173042021-06-21 09:36:20 +00001328 boolean allowed = isActivityAllowed(topTask);
Mayank Gargbfa66132021-05-05 19:56:20 -07001329 if (Log.isLoggable(TAG, Log.DEBUG)) {
1330 Slog.d(TAG, "new activity:" + topTask.toString() + " allowed:" + allowed);
Keun-young Park4727da32016-05-31 10:00:51 -07001331 }
Ram Periathiruvadibf0eab72018-02-06 12:32:43 -08001332 if (allowed) {
1333 return;
1334 }
Keun young Park40fcb0c2021-09-14 18:47:28 -07001335 if (!mEnableActivityBlocking) {
1336 Slog.d(TAG, "Current activity " + topTask.topActivity
1337 + " not allowed, blocking disabled. Number of tasks in stack:"
1338 + topTask.taskInfo.childTaskIds.length);
1339 return;
Ram Periathiruvadibf0eab72018-02-06 12:32:43 -08001340 }
Mayank Gargbfa66132021-05-05 19:56:20 -07001341 if (Log.isLoggable(TAG, Log.DEBUG)) {
1342 Slog.d(TAG, "Current activity " + topTask.topActivity
Eric Jeong47b1e242020-12-21 13:41:36 -08001343 + " not allowed, will block, number of tasks in stack:"
1344 + topTask.taskInfo.childTaskIds.length);
Keun-young Park4727da32016-05-31 10:00:51 -07001345 }
Yao, Yuxingd1d6a372018-05-08 10:37:43 -07001346
Yao, Yuxing14e83b42018-10-29 18:29:56 -07001347 // Figure out the root activity of blocked task.
1348 String taskRootActivity = null;
Louis Chang3bf2f202020-08-18 13:04:28 +08001349 for (int i = 0; i < topTask.taskInfo.childTaskIds.length; i++) {
Yao, Yuxingd1d6a372018-05-08 10:37:43 -07001350 // topTask.taskId is the task that should be blocked.
Louis Chang3bf2f202020-08-18 13:04:28 +08001351 if (topTask.taskInfo.childTaskIds[i] == topTask.taskId) {
Yao, Yuxingd1d6a372018-05-08 10:37:43 -07001352 // stackInfo represents an ActivityStack. Its fields taskIds and taskNames
1353 // are 1:1 mapped, where taskNames is the name of root activity in this task.
Louis Chang3bf2f202020-08-18 13:04:28 +08001354 taskRootActivity = topTask.taskInfo.childTaskNames[i];
Yao, Yuxingd1d6a372018-05-08 10:37:43 -07001355 break;
1356 }
1357 }
Yao, Yuxing14e83b42018-10-29 18:29:56 -07001358
1359 boolean isRootDO = false;
1360 if (taskRootActivity != null) {
Gaurav Bhola83173042021-06-21 09:36:20 +00001361 ComponentName taskRootComponentName =
1362 ComponentName.unflattenFromString(taskRootActivity);
Yao, Yuxing14e83b42018-10-29 18:29:56 -07001363 isRootDO = isActivityDistractionOptimized(
Gaurav Bhola83173042021-06-21 09:36:20 +00001364 taskRootComponentName.getPackageName(), taskRootComponentName.getClassName());
Yao, Yuxing14e83b42018-10-29 18:29:56 -07001365 }
1366
1367 Intent newActivityIntent = createBlockingActivityIntent(
Yao, Yuxingd525de12019-05-06 15:11:48 -07001368 mActivityBlockingActivity, topTask.displayId,
1369 topTask.topActivity.flattenToShortString(), topTask.taskId, taskRootActivity,
1370 isRootDO);
Yao, Yuxing14e83b42018-10-29 18:29:56 -07001371
1372 // Intent contains all info to debug what is blocked - log into both logcat and dumpsys.
1373 String log = "Starting blocking activity with intent: " + newActivityIntent.toUri(0);
Mayank Gargbfa66132021-05-05 19:56:20 -07001374 if (Log.isLoggable(TAG, Log.INFO)) {
1375 Slog.i(TAG, log);
Yao, Yuxing14e83b42018-10-29 18:29:56 -07001376 }
Bin Tan2536d402021-02-10 15:28:35 -08001377 mBlockedActivityLogs.log(log);
Ram Periathiruvadi38388302018-02-22 16:42:49 -08001378 mSystemActivityMonitoringService.blockActivity(topTask, newActivityIntent);
Keun-young Park4727da32016-05-31 10:00:51 -07001379 }
1380
Gaurav Bhola83173042021-06-21 09:36:20 +00001381 private boolean isActivityAllowed(TopTaskInfoContainer topTaskInfoContainer) {
1382 ComponentName activityName = topTaskInfoContainer.topActivity;
Gaurav Bholaafd79ef2021-06-16 13:22:03 +00001383 boolean isDistractionOptimized = isActivityDistractionOptimized(
1384 activityName.getPackageName(),
1385 activityName.getClassName());
1386 if (!isDistractionOptimized) {
1387 return false;
1388 }
1389 return !(mPreventTemplatedAppsFromShowingDialog
1390 && isTemplateActivity(activityName)
Gaurav Bhola83173042021-06-21 09:36:20 +00001391 && isActivityShowingADialogOnDisplay(activityName, topTaskInfoContainer.displayId));
Gaurav Bholaafd79ef2021-06-16 13:22:03 +00001392 }
1393
1394 private boolean isTemplateActivity(ComponentName activityName) {
1395 // TODO(b/191263486): Finalise on how to detect the templated activities.
1396 return activityName.getClassName().equals(mTemplateActivityClassName);
1397 }
1398
Gaurav Bhola83173042021-06-21 09:36:20 +00001399 private boolean isActivityShowingADialogOnDisplay(ComponentName activityName, int displayId) {
Gaurav Bholaafd79ef2021-06-16 13:22:03 +00001400 String output = dumpWindows();
1401 List<WindowDumpParser.Window> appWindows =
Gaurav Bhola83173042021-06-21 09:36:20 +00001402 WindowDumpParser.getParsedAppWindows(output, activityName.getPackageName());
Gaurav Bhola38569c72021-06-30 15:36:20 +00001403 // TODO(b/192354699): Handle case where an activity can have multiple instances on the same
1404 // display.
1405 int totalAppWindows = appWindows.size();
1406 String firstActivityRecord = null;
1407 int numTopActivityAppWindowsOnDisplay = 0;
1408 for (int i = 0; i < totalAppWindows; i++) {
1409 WindowDumpParser.Window appWindow = appWindows.get(i);
1410 if (appWindow.getDisplayId() != displayId) {
1411 continue;
1412 }
1413 if (TextUtils.isEmpty(appWindow.getActivityRecord())) {
1414 continue;
1415 }
1416 if (firstActivityRecord == null) {
1417 firstActivityRecord = appWindow.getActivityRecord();
1418 }
1419 if (firstActivityRecord.equals(appWindow.getActivityRecord())) {
1420 numTopActivityAppWindowsOnDisplay++;
1421 }
Gaurav Bholaafd79ef2021-06-16 13:22:03 +00001422 }
Gaurav Bhola83173042021-06-21 09:36:20 +00001423 Slogf.d(TAG, "Top activity = " + activityName);
Gaurav Bhola38569c72021-06-30 15:36:20 +00001424 Slogf.d(TAG, "Number of app widows of top activity = " + numTopActivityAppWindowsOnDisplay);
1425 boolean isShowingADialog = numTopActivityAppWindowsOnDisplay > 1;
Gaurav Bhola83173042021-06-21 09:36:20 +00001426 synchronized (mLock) {
1427 if (isShowingADialog) {
1428 mTopActivityWithDialogPerDisplay.put(displayId, activityName);
1429 } else {
1430 mTopActivityWithDialogPerDisplay.remove(displayId);
Gaurav Bholaafd79ef2021-06-16 13:22:03 +00001431 }
1432 }
Gaurav Bhola83173042021-06-21 09:36:20 +00001433 return isShowingADialog;
Gaurav Bholaafd79ef2021-06-16 13:22:03 +00001434 }
1435
1436 private String dumpWindows() {
1437 try {
1438 ParcelFileDescriptor[] fileDescriptors = ParcelFileDescriptor.createSocketPair();
1439 mWindowManagerBinder.dump(
1440 fileDescriptors[0].getFileDescriptor(), WINDOW_DUMP_ARGUMENTS);
1441 fileDescriptors[0].close();
1442 StringBuilder outputBuilder = new StringBuilder();
1443 BufferedReader reader = new BufferedReader(
1444 new FileReader(fileDescriptors[1].getFileDescriptor()));
1445 String line;
1446 while ((line = reader.readLine()) != null) {
1447 outputBuilder.append(line).append("\n");
1448 }
1449 reader.close();
1450 fileDescriptors[1].close();
1451 return outputBuilder.toString();
1452 } catch (IOException | RemoteException e) {
1453 throw new RuntimeException(e);
1454 }
1455 }
1456
Yao, Yuxing14e83b42018-10-29 18:29:56 -07001457 /**
1458 * Creates an intent to start blocking activity.
1459 *
1460 * @param blockingActivity the activity to launch
Jordan Jozwiak12d59e02019-06-20 18:10:21 -07001461 * @param blockedActivity the activity being blocked
1462 * @param blockedTaskId the blocked task id, which contains the blocked activity
Yao, Yuxing14e83b42018-10-29 18:29:56 -07001463 * @param taskRootActivity root activity of the blocked task
Gaurav Bhola83173042021-06-21 09:36:20 +00001464 * @param isRootDo denotes if the root activity is distraction optimised
Yao, Yuxing14e83b42018-10-29 18:29:56 -07001465 * @return an intent to launch the blocking activity.
1466 */
1467 private static Intent createBlockingActivityIntent(ComponentName blockingActivity,
Yao, Yuxingd525de12019-05-06 15:11:48 -07001468 int displayId, String blockedActivity, int blockedTaskId, String taskRootActivity,
1469 boolean isRootDo) {
Yao, Yuxing14e83b42018-10-29 18:29:56 -07001470 Intent newActivityIntent = new Intent();
Yao, Yuxingd525de12019-05-06 15:11:48 -07001471 newActivityIntent.setFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
Yao, Yuxing14e83b42018-10-29 18:29:56 -07001472 newActivityIntent.setComponent(blockingActivity);
1473 newActivityIntent.putExtra(
Yao, Yuxingd525de12019-05-06 15:11:48 -07001474 BLOCKING_INTENT_EXTRA_DISPLAY_ID, displayId);
1475 newActivityIntent.putExtra(
Yao, Yuxing14e83b42018-10-29 18:29:56 -07001476 BLOCKING_INTENT_EXTRA_BLOCKED_ACTIVITY_NAME, blockedActivity);
1477 newActivityIntent.putExtra(
1478 BLOCKING_INTENT_EXTRA_BLOCKED_TASK_ID, blockedTaskId);
1479 newActivityIntent.putExtra(
1480 BLOCKING_INTENT_EXTRA_ROOT_ACTIVITY_NAME, taskRootActivity);
1481 newActivityIntent.putExtra(
1482 BLOCKING_INTENT_EXTRA_IS_ROOT_ACTIVITY_DO, isRootDo);
Yao, Yuxingcfcc59f2019-03-05 16:35:47 -08001483
Yao, Yuxing14e83b42018-10-29 18:29:56 -07001484 return newActivityIntent;
1485 }
1486
Ram Periathiruvadicdee1202018-07-17 18:01:31 -07001487 /**
1488 * Enable/Disable activity blocking by correspondingly enabling/disabling broadcasting UXR
1489 * changes in {@link CarUxRestrictionsManagerService}. This is only available in
1490 * engineering builds for development convenience.
Ram Periathiruvadicdee1202018-07-17 18:01:31 -07001491 */
Ram Periathiruvadia6e0d9b2018-04-25 20:19:22 -07001492 @Override
Yan Zhu211b1fe2019-11-06 15:54:19 -08001493 public void setEnableActivityBlocking(boolean enable) {
Ram Periathiruvadicdee1202018-07-17 18:01:31 -07001494 if (!isDebugBuild()) {
Mayank Gargbfa66132021-05-05 19:56:20 -07001495 Slog.e(TAG, "Cannot enable/disable activity blocking");
Ram Periathiruvadicdee1202018-07-17 18:01:31 -07001496 return;
1497 }
Yan Zhu211b1fe2019-11-06 15:54:19 -08001498
Ram Periathiruvadia6e0d9b2018-04-25 20:19:22 -07001499 // Check if the caller has the same signature as that of the car service.
1500 if (mPackageManager.checkSignatures(Process.myUid(), Binder.getCallingUid())
1501 != PackageManager.SIGNATURE_MATCH) {
1502 throw new SecurityException(
1503 "Caller " + mPackageManager.getNameForUid(Binder.getCallingUid())
Mayank Garg31e73042020-01-23 00:10:38 -08001504 + " does not have the right signature");
Ram Periathiruvadia6e0d9b2018-04-25 20:19:22 -07001505 }
Ram Periathiruvadicdee1202018-07-17 18:01:31 -07001506 mCarUxRestrictionsService.setUxRChangeBroadcastEnabled(enable);
Ram Periathiruvadibf0eab72018-02-06 12:32:43 -08001507 }
1508
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001509 /**
Ram Periathiruvadi38388302018-02-22 16:42:49 -08001510 * Get the distraction optimized activities for the given package.
1511 *
1512 * @param pkgName Name of the package
1513 * @return Array of the distraction optimized activities in the package
1514 */
1515 @Nullable
1516 public String[] getDistractionOptimizedActivities(String pkgName) {
1517 try {
Keun young Park40fcb0c2021-09-14 18:47:28 -07001518 return findDistractionOptimizedActivitiesAsUser(pkgName,
Yao, Yuxing0c6fc732019-05-10 14:58:49 -07001519 mActivityManager.getCurrentUser());
Ram Periathiruvadi38388302018-02-22 16:42:49 -08001520 } catch (NameNotFoundException e) {
1521 return null;
1522 }
1523 }
Ram Periathiruvadie6e2ac32018-05-02 14:57:46 -07001524
Keun young Park40fcb0c2021-09-14 18:47:28 -07001525 private String[] findDistractionOptimizedActivitiesAsUser(String pkgName, int userId)
1526 throws NameNotFoundException {
1527 String regionString;
1528 synchronized (mLock) {
1529 regionString = mCurrentDrivingSafetyRegion;
1530 }
1531 return CarAppMetadataReader.findDistractionOptimizedActivitiesAsUser(mContext, pkgName,
1532 userId, regionString);
1533 }
1534
Ram Periathiruvadi38388302018-02-22 16:42:49 -08001535 /**
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001536 * Reading policy and setting policy can take time. Run it in a separate handler thread.
1537 */
Keun young Parkb241d022020-04-20 20:31:34 -07001538 private static final class PackageHandler extends Handler {
Mayank Garg72c71d22021-02-03 23:54:45 -08001539 private static final String TAG = CarLog.tagFor(CarPackageManagerService.class);
Keun young Parkb241d022020-04-20 20:31:34 -07001540
Keun young Park6c4fd342019-12-13 12:46:04 -08001541 private static final int MSG_INIT = 0;
1542 private static final int MSG_PARSE_PKG = 1;
1543 private static final int MSG_UPDATE_POLICY = 2;
1544 private static final int MSG_RELEASE = 3;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001545
Keun young Parkb241d022020-04-20 20:31:34 -07001546 private final WeakReference<CarPackageManagerService> mService;
1547
1548 private PackageHandler(Looper looper, CarPackageManagerService service) {
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001549 super(looper);
Keun young Parkb241d022020-04-20 20:31:34 -07001550 mService = new WeakReference<CarPackageManagerService>(service);
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001551 }
1552
1553 private void requestInit() {
1554 Message msg = obtainMessage(MSG_INIT);
1555 sendMessage(msg);
1556 }
1557
1558 private void requestRelease() {
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001559 removeMessages(MSG_UPDATE_POLICY);
Keun-young Park6dcc50b2016-10-10 19:01:11 -07001560 Message msg = obtainMessage(MSG_RELEASE);
1561 sendMessage(msg);
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001562 }
1563
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001564 private void requestUpdatingPolicy(String packageName, CarAppBlockingPolicy policy,
1565 int flags) {
1566 Pair<String, CarAppBlockingPolicy> pair = new Pair<>(packageName, policy);
1567 Message msg = obtainMessage(MSG_UPDATE_POLICY, flags, 0, pair);
1568 sendMessage(msg);
1569 }
1570
Mayank Gargfde5e662021-01-19 22:21:10 -08001571 private void requestParsingInstalledPkg(String packageName) {
1572 Message msg = obtainMessage(MSG_PARSE_PKG, packageName);
1573 sendMessage(msg);
Ram Periathiruvadi38388302018-02-22 16:42:49 -08001574 }
1575
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001576 @Override
1577 public void handleMessage(Message msg) {
Keun young Parkb241d022020-04-20 20:31:34 -07001578 CarPackageManagerService service = mService.get();
1579 if (service == null) {
Eric Jeong47b1e242020-12-21 13:41:36 -08001580 Slog.i(TAG, "handleMessage null service");
Keun young Parkb241d022020-04-20 20:31:34 -07001581 return;
1582 }
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001583 switch (msg.what) {
1584 case MSG_INIT:
Keun young Parkb241d022020-04-20 20:31:34 -07001585 service.doHandleInit();
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001586 break;
Ram Periathiruvadi38388302018-02-22 16:42:49 -08001587 case MSG_PARSE_PKG:
Mayank Gargfde5e662021-01-19 22:21:10 -08001588 service.doParseInstalledPackage((String) msg.obj);
Ram Periathiruvadi38388302018-02-22 16:42:49 -08001589 break;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001590 case MSG_UPDATE_POLICY:
1591 Pair<String, CarAppBlockingPolicy> pair =
1592 (Pair<String, CarAppBlockingPolicy>) msg.obj;
Keun young Parkb241d022020-04-20 20:31:34 -07001593 service.doUpdatePolicy(pair.first, pair.second, msg.arg1);
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001594 break;
Keun-young Park6dcc50b2016-10-10 19:01:11 -07001595 case MSG_RELEASE:
Keun young Parkb241d022020-04-20 20:31:34 -07001596 service.doHandleRelease();
Keun-young Park6dcc50b2016-10-10 19:01:11 -07001597 break;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001598 }
1599 }
1600 }
1601
1602 private static class AppBlockingPackageInfoWrapper {
1603 private final AppBlockingPackageInfo info;
1604 /**
1605 * Whether the current info is matching with the target package in system. Mismatch can
1606 * happen for version out of range or signature mismatch.
1607 */
1608 private boolean isMatching;
1609
1610 private AppBlockingPackageInfoWrapper(AppBlockingPackageInfo info, boolean isMatching) {
Ram Periathiruvadie6e2ac32018-05-02 14:57:46 -07001611 this.info = info;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001612 this.isMatching = isMatching;
1613 }
1614
1615 @Override
1616 public String toString() {
1617 return "AppBlockingPackageInfoWrapper [info=" + info + ", isMatching=" + isMatching +
1618 "]";
1619 }
1620 }
1621
1622 /**
1623 * Client policy holder per each client. Should be accessed with CarpackageManagerService.this
1624 * held.
1625 */
1626 private static class ClientPolicy {
Jordan Jozwiak794abcb2020-07-27 08:08:11 -07001627 private final HashMap<String, AppBlockingPackageInfoWrapper> mAllowlistsMap =
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001628 new HashMap<>();
Jordan Jozwiak794abcb2020-07-27 08:08:11 -07001629 private final HashMap<String, AppBlockingPackageInfoWrapper> mBlocklistsMap =
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001630 new HashMap<>();
1631
Jordan Jozwiak794abcb2020-07-27 08:08:11 -07001632 private void replaceAllowlists(AppBlockingPackageInfoWrapper[] allowlists) {
1633 mAllowlistsMap.clear();
1634 addToAllowlists(allowlists);
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001635 }
1636
Jordan Jozwiak794abcb2020-07-27 08:08:11 -07001637 private void addToAllowlists(AppBlockingPackageInfoWrapper[] allowlists) {
1638 if (allowlists == null) {
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001639 return;
1640 }
Jordan Jozwiak794abcb2020-07-27 08:08:11 -07001641 for (AppBlockingPackageInfoWrapper wrapper : allowlists) {
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001642 if (wrapper != null) {
Jordan Jozwiak794abcb2020-07-27 08:08:11 -07001643 mAllowlistsMap.put(wrapper.info.packageName, wrapper);
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001644 }
1645 }
1646 }
1647
Jordan Jozwiak794abcb2020-07-27 08:08:11 -07001648 private void removeAllowlists(AppBlockingPackageInfoWrapper[] allowlists) {
1649 if (allowlists == null) {
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001650 return;
1651 }
Jordan Jozwiak794abcb2020-07-27 08:08:11 -07001652 for (AppBlockingPackageInfoWrapper wrapper : allowlists) {
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001653 if (wrapper != null) {
Jordan Jozwiak794abcb2020-07-27 08:08:11 -07001654 mAllowlistsMap.remove(wrapper.info.packageName);
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001655 }
1656 }
1657 }
1658
Jordan Jozwiak794abcb2020-07-27 08:08:11 -07001659 private void replaceBlocklists(AppBlockingPackageInfoWrapper[] blocklists) {
1660 mBlocklistsMap.clear();
1661 addToBlocklists(blocklists);
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001662 }
1663
Jordan Jozwiak794abcb2020-07-27 08:08:11 -07001664 private void addToBlocklists(AppBlockingPackageInfoWrapper[] blocklists) {
1665 if (blocklists == null) {
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001666 return;
1667 }
Jordan Jozwiak794abcb2020-07-27 08:08:11 -07001668 for (AppBlockingPackageInfoWrapper wrapper : blocklists) {
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001669 if (wrapper != null) {
Jordan Jozwiak794abcb2020-07-27 08:08:11 -07001670 mBlocklistsMap.put(wrapper.info.packageName, wrapper);
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001671 }
1672 }
1673 }
1674
Jordan Jozwiak794abcb2020-07-27 08:08:11 -07001675 private void removeBlocklists(AppBlockingPackageInfoWrapper[] blocklists) {
1676 if (blocklists == null) {
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001677 return;
1678 }
Jordan Jozwiak794abcb2020-07-27 08:08:11 -07001679 for (AppBlockingPackageInfoWrapper wrapper : blocklists) {
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001680 if (wrapper != null) {
Jordan Jozwiak794abcb2020-07-27 08:08:11 -07001681 mBlocklistsMap.remove(wrapper.info.packageName);
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001682 }
1683 }
1684 }
1685 }
Keun-young Park4727da32016-05-31 10:00:51 -07001686
1687 private class ActivityLaunchListener
Ram Periathiruvadie6e2ac32018-05-02 14:57:46 -07001688 implements SystemActivityMonitoringService.ActivityLaunchListener {
Keun-young Park4727da32016-05-31 10:00:51 -07001689 @Override
1690 public void onActivityLaunch(TopTaskInfoContainer topTask) {
Yao, Yuxing2646cff2019-04-23 17:01:26 -07001691 if (topTask == null) {
Mayank Gargbfa66132021-05-05 19:56:20 -07001692 Slog.e(TAG, "Received callback with null top task.");
Yao, Yuxing2646cff2019-04-23 17:01:26 -07001693 return;
1694 }
Keun-young Park4727da32016-05-31 10:00:51 -07001695 blockTopActivityIfNecessary(topTask);
1696 }
1697 }
1698
Ram Periathiruvadi2da6d0e2018-01-26 18:02:10 -08001699 /**
1700 * Listens to the UX restrictions from {@link CarUxRestrictionsManagerService} and initiates
1701 * checking if the foreground Activity should be blocked.
1702 */
1703 private class UxRestrictionsListener extends ICarUxRestrictionsChangeListener.Stub {
Yan Zhu211b1fe2019-11-06 15:54:19 -08001704 @GuardedBy("mLock")
Ram Periathiruvadi2da6d0e2018-01-26 18:02:10 -08001705 @Nullable
1706 private CarUxRestrictions mCurrentUxRestrictions;
1707 private final CarUxRestrictionsManagerService uxRestrictionsService;
Keun-young Park4727da32016-05-31 10:00:51 -07001708
Ram Periathiruvadi2da6d0e2018-01-26 18:02:10 -08001709 public UxRestrictionsListener(CarUxRestrictionsManagerService service) {
1710 uxRestrictionsService = service;
Ram Periathiruvadi2da6d0e2018-01-26 18:02:10 -08001711 }
1712
1713 @Override
1714 public void onUxRestrictionsChanged(CarUxRestrictions restrictions) {
Mayank Gargbfa66132021-05-05 19:56:20 -07001715 if (Log.isLoggable(TAG, Log.DEBUG)) {
1716 Slog.d(TAG, "Received uxr restrictions: "
1717 + restrictions.isRequiresDistractionOptimization() + " : "
1718 + restrictions.getActiveRestrictions());
Ram Periathiruvadi2da6d0e2018-01-26 18:02:10 -08001719 }
Ram Periathiruvadic57678d2018-04-23 09:18:33 -07001720
Yan Zhu211b1fe2019-11-06 15:54:19 -08001721 synchronized (mLock) {
Ram Periathiruvadi2da6d0e2018-01-26 18:02:10 -08001722 mCurrentUxRestrictions = new CarUxRestrictions(restrictions);
1723 }
1724 checkIfTopActivityNeedsBlocking();
1725 }
1726
1727 private void checkIfTopActivityNeedsBlocking() {
1728 boolean shouldCheck = false;
Yan Zhu211b1fe2019-11-06 15:54:19 -08001729 synchronized (mLock) {
Ram Periathiruvadi2da6d0e2018-01-26 18:02:10 -08001730 if (mCurrentUxRestrictions != null
1731 && mCurrentUxRestrictions.isRequiresDistractionOptimization()) {
1732 shouldCheck = true;
Keun-young Park4727da32016-05-31 10:00:51 -07001733 }
1734 }
Mayank Gargbfa66132021-05-05 19:56:20 -07001735 if (Log.isLoggable(TAG, Log.DEBUG)) {
1736 Slog.d(TAG, "Should check top tasks?: " + shouldCheck);
Ram Periathiruvadi2da6d0e2018-01-26 18:02:10 -08001737 }
1738 if (shouldCheck) {
Yao, Yuxingd525de12019-05-06 15:11:48 -07001739 // Loop over all top tasks to ensure tasks on virtual display can also be blocked.
Keun-young Park4727da32016-05-31 10:00:51 -07001740 blockTopActivitiesIfNecessary();
1741 }
1742 }
1743
Yan Zhu211b1fe2019-11-06 15:54:19 -08001744 private boolean isRestricted() {
Ram Periathiruvadi2da6d0e2018-01-26 18:02:10 -08001745 // if current restrictions is null, try querying the service, once.
Yan Zhu211b1fe2019-11-06 15:54:19 -08001746 synchronized (mLock) {
1747 if (mCurrentUxRestrictions == null) {
1748 mCurrentUxRestrictions = uxRestrictionsService.getCurrentUxRestrictions();
1749 }
1750 if (mCurrentUxRestrictions != null) {
1751 return mCurrentUxRestrictions.isRequiresDistractionOptimization();
1752 }
Ram Periathiruvadi2da6d0e2018-01-26 18:02:10 -08001753 }
Yan Zhu211b1fe2019-11-06 15:54:19 -08001754
Ram Periathiruvadi2da6d0e2018-01-26 18:02:10 -08001755 // If restriction information is still not available (could happen during bootup),
1756 // return not restricted. This maintains parity with previous implementation but needs
1757 // a revisit as we test more.
1758 return false;
Keun-young Park4727da32016-05-31 10:00:51 -07001759 }
1760 }
Ram Periathiruvadi38388302018-02-22 16:42:49 -08001761
1762 /**
Gaurav Bholaafd79ef2021-06-16 13:22:03 +00001763 * Called when a window change event is received by the {@link CarSafetyAccessibilityService}.
1764 */
1765 @VisibleForTesting
1766 void onWindowChangeEvent() {
1767 Slogf.d(TAG, "onWindowChange event received");
1768 mHandlerThread.getThreadHandler().post(() -> blockTopActivitiesIfNecessary());
1769 }
1770
1771 /**
Ram Periathiruvadie6e2ac32018-05-02 14:57:46 -07001772 * Listens to the package install/uninstall events to know when to initiate parsing
1773 * installed packages.
1774 */
1775 private class PackageParsingEventReceiver extends BroadcastReceiver {
Ram Periathiruvadie6e2ac32018-05-02 14:57:46 -07001776 @Override
1777 public void onReceive(Context context, Intent intent) {
1778 if (intent == null || intent.getAction() == null) {
1779 return;
1780 }
Mayank Gargbfa66132021-05-05 19:56:20 -07001781 if (Log.isLoggable(TAG, Log.DEBUG)) {
1782 Slog.d(TAG, "PackageParsingEventReceiver Received " + intent.getAction());
Ram Periathiruvadie6e2ac32018-05-02 14:57:46 -07001783 }
1784 String action = intent.getAction();
1785 if (isPackageManagerAction(action)) {
Ram Periathiruvadi295954d2018-04-10 18:27:28 -07001786 // send a delayed message so if we received multiple related intents, we parse
1787 // only once.
1788 logEventChange(intent);
Mayank Gargfde5e662021-01-19 22:21:10 -08001789 String packageName = getPackageName(intent);
1790 mHandler.requestParsingInstalledPkg(packageName);
Ram Periathiruvadi295954d2018-04-10 18:27:28 -07001791 }
1792 }
1793
Mayank Gargfde5e662021-01-19 22:21:10 -08001794 private String getPackageName(Intent intent) {
1795 // For mPackageManagerActions, data should contain package name.
1796 String dataString = intent.getDataString();
1797 if (dataString == null) return null;
1798
1799 String scheme = intent.getScheme();
1800 if (!scheme.equals("package")) return null;
1801
1802 String[] splitData = intent.getDataString().split(":");
1803 if (splitData.length < 2) return null;
1804
1805 return splitData[1];
1806 }
1807
Ram Periathiruvadi295954d2018-04-10 18:27:28 -07001808 private boolean isPackageManagerAction(String action) {
Jordan Jozwiak12d59e02019-06-20 18:10:21 -07001809 return mPackageManagerActions.contains(action);
Ram Periathiruvadi295954d2018-04-10 18:27:28 -07001810 }
1811
1812 /**
1813 * Convenience log function to log what changed. Logs only when more debug logs
1814 * are needed - DBG_POLICY_CHECK needs to be true
1815 */
1816 private void logEventChange(Intent intent) {
Mayank Gargbfa66132021-05-05 19:56:20 -07001817 if (intent == null) {
Ram Periathiruvadi295954d2018-04-10 18:27:28 -07001818 return;
1819 }
Mayank Gargbfa66132021-05-05 19:56:20 -07001820 if (Log.isLoggable(TAG, Log.DEBUG)) {
1821 String packageName = intent.getData().getSchemeSpecificPart();
1822 Slog.d(TAG, "Pkg Changed:" + packageName);
1823 String action = intent.getAction();
1824 if (action == null) {
1825 return;
Ram Periathiruvadi295954d2018-04-10 18:27:28 -07001826 }
Mayank Gargbfa66132021-05-05 19:56:20 -07001827 if (action.equals(Intent.ACTION_PACKAGE_CHANGED)) {
1828 Slog.d(TAG, "Changed components");
1829 String[] cc = intent
1830 .getStringArrayExtra(Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST);
1831 if (cc != null) {
1832 for (String c : cc) {
1833 Slog.d(TAG, c);
1834 }
1835 }
1836 } else if (action.equals(Intent.ACTION_PACKAGE_REMOVED)
1837 || action.equals(Intent.ACTION_PACKAGE_ADDED)) {
1838 Slog.d(TAG, action + " Replacing?: "
1839 + intent.getBooleanExtra(Intent.EXTRA_REPLACING, false));
1840 }
Ram Periathiruvadi38388302018-02-22 16:42:49 -08001841 }
1842 }
1843 }
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001844}