blob: 80374ea00892a2121bfcf822cfeb75458a3b6c61 [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
Yao, Yuxing4c3b93c2019-02-20 09:00:01 -080019import android.annotation.NonNull;
Ram Periathiruvadi2da6d0e2018-01-26 18:02:10 -080020import android.annotation.Nullable;
Yao, Yuxing0c6fc732019-05-10 14:58:49 -070021import android.app.ActivityManager;
Louis Chang3bf2f202020-08-18 13:04:28 +080022import android.app.ActivityTaskManager.RootTaskInfo;
Arnaud Berryd1f88ee2020-02-19 13:49:31 -080023import android.app.PendingIntent;
Keun-young Parke54ac272016-02-16 19:02:18 -080024import android.car.Car;
25import android.car.content.pm.AppBlockingPackageInfo;
26import android.car.content.pm.CarAppBlockingPolicy;
27import android.car.content.pm.CarAppBlockingPolicyService;
28import android.car.content.pm.CarPackageManager;
29import android.car.content.pm.ICarPackageManager;
Ram Periathiruvadi2da6d0e2018-01-26 18:02:10 -080030import android.car.drivingstate.CarUxRestrictions;
31import android.car.drivingstate.ICarUxRestrictionsChangeListener;
Antonio Kantekf7007532020-03-17 10:37:58 -070032import android.car.user.CarUserManager;
33import android.car.user.CarUserManager.UserLifecycleListener;
Ram Periathiruvadi38388302018-02-22 16:42:49 -080034import android.content.BroadcastReceiver;
Keun-young Park4727da32016-05-31 10:00:51 -070035import android.content.ComponentName;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -080036import android.content.Context;
37import android.content.Intent;
Ram Periathiruvadi38388302018-02-22 16:42:49 -080038import android.content.IntentFilter;
39import android.content.pm.ActivityInfo;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -080040import android.content.pm.PackageInfo;
41import android.content.pm.PackageManager;
42import android.content.pm.PackageManager.NameNotFoundException;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -080043import android.content.pm.ResolveInfo;
Pavel Maltsev0d07c762016-11-03 16:40:15 -070044import android.content.pm.ServiceInfo;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -080045import android.content.pm.Signature;
Keun-young Park4727da32016-05-31 10:00:51 -070046import android.content.res.Resources;
Yao, Yuxingd525de12019-05-06 15:11:48 -070047import android.hardware.display.DisplayManager;
Ram Periathiruvadia6e0d9b2018-04-25 20:19:22 -070048import android.os.Binder;
Ram Periathiruvadid937c322018-06-13 12:28:12 -070049import android.os.Build;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -080050import android.os.Handler;
51import android.os.HandlerThread;
52import android.os.Looper;
53import android.os.Message;
Ram Periathiruvadia6e0d9b2018-04-25 20:19:22 -070054import android.os.Process;
Yao, Yuxing0c6fc732019-05-10 14:58:49 -070055import android.os.UserHandle;
Yao, Yuxingd1d6a372018-05-08 10:37:43 -070056import android.text.format.DateFormat;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -080057import android.util.ArraySet;
58import android.util.Log;
59import android.util.Pair;
Eric Jeong47b1e242020-12-21 13:41:36 -080060import android.util.Slog;
Yao, Yuxingd525de12019-05-06 15:11:48 -070061import android.util.SparseArray;
Yao, Yuxingcfcc59f2019-03-05 16:35:47 -080062import android.view.Display;
Yao, Yuxingd525de12019-05-06 15:11:48 -070063import android.view.DisplayAddress;
Ram Periathiruvadi8ef1a202018-03-16 17:49:21 -070064
Keun-young Park4aeb4bf2015-12-08 18:31:33 -080065import com.android.car.CarLog;
66import com.android.car.CarServiceBase;
67import com.android.car.CarServiceUtils;
Ram Periathiruvadi2da6d0e2018-01-26 18:02:10 -080068import com.android.car.CarUxRestrictionsManagerService;
Keun-young Park4727da32016-05-31 10:00:51 -070069import com.android.car.R;
70import com.android.car.SystemActivityMonitoringService;
71import com.android.car.SystemActivityMonitoringService.TopTaskInfoContainer;
Mayank Garg31e73042020-01-23 00:10:38 -080072import com.android.car.user.CarUserService;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -080073import com.android.internal.annotations.GuardedBy;
Ram Periathiruvadi8ef1a202018-03-16 17:49:21 -070074import com.android.internal.annotations.VisibleForTesting;
Ram Periathiruvadi38388302018-02-22 16:42:49 -080075
Jordan Jozwiak12d59e02019-06-20 18:10:21 -070076import com.google.android.collect.Sets;
77
Keun-young Park4aeb4bf2015-12-08 18:31:33 -080078import java.io.PrintWriter;
Keun young Parkb241d022020-04-20 20:31:34 -070079import java.lang.ref.WeakReference;
Ram Periathiruvadi38388302018-02-22 16:42:49 -080080import java.util.ArrayList;
Ram Periathiruvadi295954d2018-04-10 18:27:28 -070081import java.util.Arrays;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -080082import java.util.HashMap;
83import java.util.LinkedList;
84import java.util.List;
Ram Periathiruvadi46a3a3d2018-03-23 16:58:32 -070085import java.util.Map;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -080086import java.util.Map.Entry;
Keun-young Park4727da32016-05-31 10:00:51 -070087import java.util.Set;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -080088
Keun-young Park4aeb4bf2015-12-08 18:31:33 -080089public class CarPackageManagerService extends ICarPackageManager.Stub implements CarServiceBase {
Ram Periathiruvadi2da6d0e2018-01-26 18:02:10 -080090 private static final boolean DBG_POLICY_SET = false;
91 private static final boolean DBG_POLICY_CHECK = false;
92 private static final boolean DBG_POLICY_ENFORCEMENT = false;
Ram Periathiruvadi46a3a3d2018-03-23 16:58:32 -070093 // Delimiters to parse packages and activities in the configuration XML resource.
94 private static final String PACKAGE_DELIMITER = ",";
95 private static final String PACKAGE_ACTIVITY_DELIMITER = "/";
Yao, Yuxingd1d6a372018-05-08 10:37:43 -070096 private static final int LOG_SIZE = 20;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -080097
98 private final Context mContext;
Mayank Garg31e73042020-01-23 00:10:38 -080099 private final CarUserService mUserService;
Keun-young Park4727da32016-05-31 10:00:51 -0700100 private final SystemActivityMonitoringService mSystemActivityMonitoringService;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800101 private final PackageManager mPackageManager;
Yao, Yuxing0c6fc732019-05-10 14:58:49 -0700102 private final ActivityManager mActivityManager;
Yao, Yuxingd525de12019-05-06 15:11:48 -0700103 private final DisplayManager mDisplayManager;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800104
Keun young Parkb241d022020-04-20 20:31:34 -0700105 private final HandlerThread mHandlerThread = CarServiceUtils.getHandlerThread(
106 getClass().getSimpleName());
107 private final PackageHandler mHandler = new PackageHandler(mHandlerThread.getLooper(), this);
Yan Zhu211b1fe2019-11-06 15:54:19 -0800108 private final Object mLock = new Object();
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800109
Yao, Yuxingd1d6a372018-05-08 10:37:43 -0700110 // For dumpsys logging.
111 private final LinkedList<String> mBlockedActivityLogs = new LinkedList<>();
112
Jordan Jozwiak794abcb2020-07-27 08:08:11 -0700113 // Store the allowlist and blocklist strings from the resource file.
114 private String mConfiguredAllowlist;
115 private String mConfiguredSystemAllowlist;
116 private String mConfiguredBlocklist;
Ram Periathiruvadid937c322018-06-13 12:28:12 -0700117 private final List<String> mAllowedAppInstallSources;
118
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800119 /**
120 * Hold policy set from policy service or client.
121 * Key: packageName of policy service
122 */
Yan Zhu211b1fe2019-11-06 15:54:19 -0800123 @GuardedBy("mLock")
Ram Periathiruvadi2da6d0e2018-01-26 18:02:10 -0800124 private final HashMap<String, ClientPolicy> mClientPolicies = new HashMap<>();
Yan Zhu211b1fe2019-11-06 15:54:19 -0800125 @GuardedBy("mLock")
Jordan Jozwiak794abcb2020-07-27 08:08:11 -0700126 private HashMap<String, AppBlockingPackageInfoWrapper> mActivityAllowlistMap = new HashMap<>();
Yan Zhu211b1fe2019-11-06 15:54:19 -0800127 @GuardedBy("mLock")
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800128 private LinkedList<AppBlockingPolicyProxy> mProxies;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800129
Yan Zhu211b1fe2019-11-06 15:54:19 -0800130 @GuardedBy("mLock")
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800131 private final LinkedList<CarAppBlockingPolicy> mWaitingPolicies = new LinkedList<>();
132
Ram Periathiruvadi2da6d0e2018-01-26 18:02:10 -0800133 private final CarUxRestrictionsManagerService mCarUxRestrictionsService;
Ram Periathiruvadibf0eab72018-02-06 12:32:43 -0800134 private boolean mEnableActivityBlocking;
Keun-young Park4727da32016-05-31 10:00:51 -0700135 private final ComponentName mActivityBlockingActivity;
136
137 private final ActivityLaunchListener mActivityLaunchListener = new ActivityLaunchListener();
Yao, Yuxingd525de12019-05-06 15:11:48 -0700138 // K: (logical) display id of a physical display, V: UXR change listener of this display.
139 // For multi-display, monitor UXR change on each display.
140 private final SparseArray<UxRestrictionsListener> mUxRestrictionsListeners =
141 new SparseArray<>();
Pavel Maltsev38da4312019-04-08 10:38:38 -0700142 private final VendorServiceController mVendorServiceController;
Ram Periathiruvadi295954d2018-04-10 18:27:28 -0700143
Jordan Jozwiak794abcb2020-07-27 08:08:11 -0700144 // Information related to when the installed packages should be parsed for building a allow and
145 // block list
Jordan Jozwiak12d59e02019-06-20 18:10:21 -0700146 private final Set<String> mPackageManagerActions = Sets.newArraySet(
Ram Periathiruvadi295954d2018-04-10 18:27:28 -0700147 Intent.ACTION_PACKAGE_ADDED,
148 Intent.ACTION_PACKAGE_CHANGED,
Ram Periathiruvadi295954d2018-04-10 18:27:28 -0700149 Intent.ACTION_PACKAGE_REMOVED,
Jordan Jozwiak12d59e02019-06-20 18:10:21 -0700150 Intent.ACTION_PACKAGE_REPLACED);
Ram Periathiruvadi295954d2018-04-10 18:27:28 -0700151
152 private final PackageParsingEventReceiver mPackageParsingEventReceiver =
153 new PackageParsingEventReceiver();
Keun-young Park4727da32016-05-31 10:00:51 -0700154
Jordan Jozwiak794abcb2020-07-27 08:08:11 -0700155 // To track if the packages have been parsed for building allow/blocklists. If we haven't had
156 // received any intents (boot complete or package changed), then the allowlist is null leading
Ram Periathiruvadic57678d2018-04-23 09:18:33 -0700157 // to blocking everything. So, no blocking until we have had a chance to parse the packages.
158 private boolean mHasParsedPackages;
159
Yao, Yuxing14e83b42018-10-29 18:29:56 -0700160 /**
161 * Name of blocked activity.
162 *
163 * @hide
164 */
165 public static final String BLOCKING_INTENT_EXTRA_BLOCKED_ACTIVITY_NAME = "blocked_activity";
166 /**
167 * int task id of the blocked task.
168 *
169 * @hide
170 */
171 public static final String BLOCKING_INTENT_EXTRA_BLOCKED_TASK_ID = "blocked_task_id";
172 /**
173 * Name of root activity of blocked task.
174 *
175 * @hide
176 */
177 public static final String BLOCKING_INTENT_EXTRA_ROOT_ACTIVITY_NAME = "root_activity_name";
178 /**
179 * Boolean indicating whether the root activity is distraction-optimized (DO).
180 * Blocking screen should show a button to restart the task if {@code true}.
181 *
182 * @hide
183 */
184 public static final String BLOCKING_INTENT_EXTRA_IS_ROOT_ACTIVITY_DO = "is_root_activity_do";
185
Yao, Yuxingd525de12019-05-06 15:11:48 -0700186 /**
187 * int display id of the blocked task.
Jordan Jozwiak12d59e02019-06-20 18:10:21 -0700188 *
Yao, Yuxingd525de12019-05-06 15:11:48 -0700189 * @hide
190 */
191 public static final String BLOCKING_INTENT_EXTRA_DISPLAY_ID = "display_id";
192
Ram Periathiruvadi2da6d0e2018-01-26 18:02:10 -0800193 public CarPackageManagerService(Context context,
194 CarUxRestrictionsManagerService uxRestrictionsService,
Mayank Garg31e73042020-01-23 00:10:38 -0800195 SystemActivityMonitoringService systemActivityMonitoringService,
196 CarUserService userService) {
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800197 mContext = context;
Mayank Garg31e73042020-01-23 00:10:38 -0800198 mUserService = userService;
Ram Periathiruvadi2da6d0e2018-01-26 18:02:10 -0800199 mCarUxRestrictionsService = uxRestrictionsService;
Keun-young Park4727da32016-05-31 10:00:51 -0700200 mSystemActivityMonitoringService = systemActivityMonitoringService;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800201 mPackageManager = mContext.getPackageManager();
Yao, Yuxing0c6fc732019-05-10 14:58:49 -0700202 mActivityManager = mContext.getSystemService(ActivityManager.class);
Yao, Yuxingd525de12019-05-06 15:11:48 -0700203 mDisplayManager = mContext.getSystemService(DisplayManager.class);
Keun-young Park4727da32016-05-31 10:00:51 -0700204 Resources res = context.getResources();
205 mEnableActivityBlocking = res.getBoolean(R.bool.enableActivityBlockingForSafety);
206 String blockingActivity = res.getString(R.string.activityBlockingActivity);
207 mActivityBlockingActivity = ComponentName.unflattenFromString(blockingActivity);
Ram Periathiruvadid937c322018-06-13 12:28:12 -0700208 mAllowedAppInstallSources = Arrays.asList(
209 res.getStringArray(R.array.allowedAppInstallSources));
Pavel Maltsev38da4312019-04-08 10:38:38 -0700210 mVendorServiceController = new VendorServiceController(
Anthony Hughfbb67762019-10-15 12:54:54 -0700211 mContext, mHandler.getLooper());
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800212 }
213
Ram Periathiruvadid937c322018-06-13 12:28:12 -0700214
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800215 @Override
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800216 public void setAppBlockingPolicy(String packageName, CarAppBlockingPolicy policy, int flags) {
217 if (DBG_POLICY_SET) {
Eric Jeong47b1e242020-12-21 13:41:36 -0800218 Slog.i(CarLog.TAG_PACKAGE, "policy setting from binder call, client:" + packageName);
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800219 }
Keun young Park6c4fd342019-12-13 12:46:04 -0800220 doSetAppBlockingPolicy(packageName, policy, flags);
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800221 }
222
Yao, Yuxingd1d6a372018-05-08 10:37:43 -0700223 /**
224 * Restarts the requested task. If task with {@code taskId} does not exist, do nothing.
225 */
226 @Override
227 public void restartTask(int taskId) {
Keun young Park572023a2020-06-03 17:29:36 -0700228 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.REAL_GET_TASKS)
229 != PackageManager.PERMISSION_GRANTED) {
230 throw new SecurityException(
231 "requires permission " + android.Manifest.permission.REAL_GET_TASKS);
232 }
Yao, Yuxingd1d6a372018-05-08 10:37:43 -0700233 mSystemActivityMonitoringService.restartTask(taskId);
234 }
235
Keun young Park6c4fd342019-12-13 12:46:04 -0800236 private void doSetAppBlockingPolicy(String packageName, CarAppBlockingPolicy policy,
237 int flags) {
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800238 if (mContext.checkCallingOrSelfPermission(Car.PERMISSION_CONTROL_APP_BLOCKING)
239 != PackageManager.PERMISSION_GRANTED) {
240 throw new SecurityException(
241 "requires permission " + Car.PERMISSION_CONTROL_APP_BLOCKING);
242 }
Enrico Granata3da3c612017-01-20 15:24:30 -0800243 CarServiceUtils.assertPackageName(mContext, packageName);
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800244 if (policy == null) {
245 throw new IllegalArgumentException("policy cannot be null");
246 }
247 if ((flags & CarPackageManager.FLAG_SET_POLICY_ADD) != 0 &&
248 (flags & CarPackageManager.FLAG_SET_POLICY_REMOVE) != 0) {
249 throw new IllegalArgumentException(
250 "Cannot set both FLAG_SET_POLICY_ADD and FLAG_SET_POLICY_REMOVE flag");
251 }
Keun young Park6c4fd342019-12-13 12:46:04 -0800252 synchronized (mLock) {
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800253 if ((flags & CarPackageManager.FLAG_SET_POLICY_WAIT_FOR_CHANGE) != 0) {
Keun young Park6c4fd342019-12-13 12:46:04 -0800254 mWaitingPolicies.add(policy);
255 }
256 }
257 mHandler.requestUpdatingPolicy(packageName, policy, flags);
258 if ((flags & CarPackageManager.FLAG_SET_POLICY_WAIT_FOR_CHANGE) != 0) {
259 synchronized (mLock) {
260 try {
261 while (mWaitingPolicies.contains(policy)) {
Keun young Parkff3196b2020-01-07 12:44:10 -0800262 mLock.wait();
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800263 }
Keun young Park6c4fd342019-12-13 12:46:04 -0800264 } catch (InterruptedException e) {
265 // Pass it over binder call
266 throw new IllegalStateException(
267 "Interrupted while waiting for policy completion", e);
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800268 }
269 }
270 }
271 }
272
273 @Override
Ram Periathiruvadie154f582018-03-21 21:53:27 -0700274 public boolean isActivityDistractionOptimized(String packageName, String className) {
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800275 assertPackageAndClassName(packageName, className);
Yan Zhu211b1fe2019-11-06 15:54:19 -0800276 synchronized (mLock) {
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800277 if (DBG_POLICY_CHECK) {
Eric Jeong47b1e242020-12-21 13:41:36 -0800278 Slog.i(CarLog.TAG_PACKAGE, "isActivityDistractionOptimized"
Ram Periathiruvadie154f582018-03-21 21:53:27 -0700279 + dumpPoliciesLocked(false));
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800280 }
Jordan Jozwiak794abcb2020-07-27 08:08:11 -0700281 AppBlockingPackageInfo info = searchFromBlocklistsLocked(packageName);
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800282 if (info != null) {
283 return false;
284 }
Jordan Jozwiak794abcb2020-07-27 08:08:11 -0700285 return isActivityInAllowlistsLocked(packageName, className);
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800286 }
287 }
288
289 @Override
Arnaud Berryd1f88ee2020-02-19 13:49:31 -0800290 public boolean isPendingIntentDistractionOptimized(PendingIntent pendingIntent) {
291 ResolveInfo info = mPackageManager.resolveActivity(
292 pendingIntent.getIntent(), PackageManager.MATCH_DEFAULT_ONLY);
293 if (info == null) return false;
294 ActivityInfo activityInfo = info.activityInfo;
295 return isActivityDistractionOptimized(activityInfo.packageName, activityInfo.name);
296 }
297
298 @Override
Ram Periathiruvadie154f582018-03-21 21:53:27 -0700299 public boolean isServiceDistractionOptimized(String packageName, String className) {
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800300 if (packageName == null) {
301 throw new IllegalArgumentException("Package name null");
302 }
Yan Zhu211b1fe2019-11-06 15:54:19 -0800303 synchronized (mLock) {
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800304 if (DBG_POLICY_CHECK) {
Eric Jeong47b1e242020-12-21 13:41:36 -0800305 Slog.i(CarLog.TAG_PACKAGE, "isServiceDistractionOptimized"
Ram Periathiruvadie154f582018-03-21 21:53:27 -0700306 + dumpPoliciesLocked(false));
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800307 }
Jordan Jozwiak794abcb2020-07-27 08:08:11 -0700308 AppBlockingPackageInfo info = searchFromBlocklistsLocked(packageName);
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800309 if (info != null) {
310 return false;
311 }
Jordan Jozwiak794abcb2020-07-27 08:08:11 -0700312 info = searchFromAllowlistsLocked(packageName);
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800313 if (info != null) {
314 return true;
315 }
316 }
317 return false;
318 }
319
Keun-young Park4727da32016-05-31 10:00:51 -0700320 @Override
321 public boolean isActivityBackedBySafeActivity(ComponentName activityName) {
Louis Chang3bf2f202020-08-18 13:04:28 +0800322 RootTaskInfo info = mSystemActivityMonitoringService.getFocusedStackForTopActivity(
Keun-young Park4727da32016-05-31 10:00:51 -0700323 activityName);
324 if (info == null) { // not top in focused stack
325 return true;
326 }
Yao, Yuxingd525de12019-05-06 15:11:48 -0700327 if (!isUxRestrictedOnDisplay(info.displayId)) {
328 return true;
329 }
Louis Chang3bf2f202020-08-18 13:04:28 +0800330 if (info.childTaskNames.length <= 1) { // nothing below this.
Keun-young Park4727da32016-05-31 10:00:51 -0700331 return false;
332 }
333 ComponentName activityBehind = ComponentName.unflattenFromString(
Louis Chang3bf2f202020-08-18 13:04:28 +0800334 info.childTaskNames[info.childTaskNames.length - 2]);
Ram Periathiruvadie154f582018-03-21 21:53:27 -0700335 return isActivityDistractionOptimized(activityBehind.getPackageName(),
Keun-young Park4727da32016-05-31 10:00:51 -0700336 activityBehind.getClassName());
337 }
338
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800339 public Looper getLooper() {
340 return mHandlerThread.getLooper();
341 }
342
343 private void assertPackageAndClassName(String packageName, String className) {
344 if (packageName == null) {
345 throw new IllegalArgumentException("Package name null");
346 }
347 if (className == null) {
348 throw new IllegalArgumentException("Class name null");
349 }
350 }
351
Yan Zhu211b1fe2019-11-06 15:54:19 -0800352 @GuardedBy("mLock")
Jordan Jozwiak794abcb2020-07-27 08:08:11 -0700353 private AppBlockingPackageInfo searchFromBlocklistsLocked(String packageName) {
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800354 for (ClientPolicy policy : mClientPolicies.values()) {
Jordan Jozwiak794abcb2020-07-27 08:08:11 -0700355 AppBlockingPackageInfoWrapper wrapper = policy.mBlocklistsMap.get(packageName);
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800356 if (wrapper != null && wrapper.isMatching) {
357 return wrapper.info;
358 }
359 }
Yao, Yuxing0c6fc732019-05-10 14:58:49 -0700360 return null;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800361 }
362
Yan Zhu211b1fe2019-11-06 15:54:19 -0800363 @GuardedBy("mLock")
Jordan Jozwiak794abcb2020-07-27 08:08:11 -0700364 private AppBlockingPackageInfo searchFromAllowlistsLocked(String packageName) {
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800365 for (ClientPolicy policy : mClientPolicies.values()) {
Jordan Jozwiak794abcb2020-07-27 08:08:11 -0700366 AppBlockingPackageInfoWrapper wrapper = policy.mAllowlistsMap.get(packageName);
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800367 if (wrapper != null && wrapper.isMatching) {
368 return wrapper.info;
369 }
370 }
Jordan Jozwiak794abcb2020-07-27 08:08:11 -0700371 AppBlockingPackageInfoWrapper wrapper = mActivityAllowlistMap.get(packageName);
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800372 return (wrapper != null) ? wrapper.info : null;
373 }
374
Yan Zhu211b1fe2019-11-06 15:54:19 -0800375 @GuardedBy("mLock")
Jordan Jozwiak794abcb2020-07-27 08:08:11 -0700376 private boolean isActivityInAllowlistsLocked(String packageName, String className) {
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800377 for (ClientPolicy policy : mClientPolicies.values()) {
Jordan Jozwiak794abcb2020-07-27 08:08:11 -0700378 if (isActivityInMapAndMatching(policy.mAllowlistsMap, packageName, className)) {
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800379 return true;
380 }
381 }
Jordan Jozwiak794abcb2020-07-27 08:08:11 -0700382 return isActivityInMapAndMatching(mActivityAllowlistMap, packageName, className);
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800383 }
384
385 private boolean isActivityInMapAndMatching(HashMap<String, AppBlockingPackageInfoWrapper> map,
386 String packageName, String className) {
387 AppBlockingPackageInfoWrapper wrapper = map.get(packageName);
388 if (wrapper == null || !wrapper.isMatching) {
Ram Periathiruvadi38388302018-02-22 16:42:49 -0800389 if (DBG_POLICY_CHECK) {
Eric Jeong47b1e242020-12-21 13:41:36 -0800390 Slog.d(CarLog.TAG_PACKAGE, "Pkg not in allowlist:" + packageName);
Ram Periathiruvadi38388302018-02-22 16:42:49 -0800391 }
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800392 return false;
393 }
394 return wrapper.info.isActivityCovered(className);
395 }
396
397 @Override
398 public void init() {
Yan Zhu211b1fe2019-11-06 15:54:19 -0800399 synchronized (mLock) {
Keun-young Park98960812016-10-04 12:50:54 -0700400 mHandler.requestInit();
Keun-young Park4727da32016-05-31 10:00:51 -0700401 }
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800402 }
403
404 @Override
405 public void release() {
Yan Zhu211b1fe2019-11-06 15:54:19 -0800406 synchronized (mLock) {
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800407 mHandler.requestRelease();
Keun-young Park6dcc50b2016-10-10 19:01:11 -0700408 // wait for release do be done. This guarantees that init is done.
409 try {
Yan Zhu211b1fe2019-11-06 15:54:19 -0800410 mLock.wait();
Keun-young Park6dcc50b2016-10-10 19:01:11 -0700411 } catch (InterruptedException e) {
Eric Jeong47b1e242020-12-21 13:41:36 -0800412 Slog.e(CarLog.TAG_PACKAGE,
Yan Zhu211b1fe2019-11-06 15:54:19 -0800413 "Interrupted wait during release");
414 Thread.currentThread().interrupt();
Keun-young Park6dcc50b2016-10-10 19:01:11 -0700415 }
Ram Periathiruvadic57678d2018-04-23 09:18:33 -0700416 mHasParsedPackages = false;
Jordan Jozwiak794abcb2020-07-27 08:08:11 -0700417 mActivityAllowlistMap.clear();
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800418 mClientPolicies.clear();
419 if (mProxies != null) {
420 for (AppBlockingPolicyProxy proxy : mProxies) {
421 proxy.disconnect();
422 }
423 mProxies.clear();
424 }
Keun young Park6c4fd342019-12-13 12:46:04 -0800425 mWaitingPolicies.clear();
Keun young Parkff3196b2020-01-07 12:44:10 -0800426 mLock.notifyAll();
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800427 }
Ram Periathiruvadi295954d2018-04-10 18:27:28 -0700428 mContext.unregisterReceiver(mPackageParsingEventReceiver);
Antonio Kantekf7007532020-03-17 10:37:58 -0700429 mUserService.removeUserLifecycleListener(mUserLifecycleListener);
Keun-young Park98960812016-10-04 12:50:54 -0700430 mSystemActivityMonitoringService.registerActivityLaunchListener(null);
Yao, Yuxingd525de12019-05-06 15:11:48 -0700431 for (int i = 0; i < mUxRestrictionsListeners.size(); i++) {
432 UxRestrictionsListener listener = mUxRestrictionsListeners.valueAt(i);
433 mCarUxRestrictionsService.unregisterUxRestrictionsChangeListener(listener);
434 }
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800435 }
436
Antonio Kantekf7007532020-03-17 10:37:58 -0700437 private final UserLifecycleListener mUserLifecycleListener = event -> {
438 if (Log.isLoggable(CarLog.TAG_PACKAGE, Log.DEBUG)) {
Eric Jeong47b1e242020-12-21 13:41:36 -0800439 Slog.d(CarLog.TAG_PACKAGE, "CarPackageManagerService.onEvent(" + event + ")");
Mayank Garg31e73042020-01-23 00:10:38 -0800440 }
Antonio Kantekf7007532020-03-17 10:37:58 -0700441 if (CarUserManager.USER_LIFECYCLE_EVENT_TYPE_SWITCHING == event.getEventType()) {
442 CarPackageManagerService.this.mHandler.requestParsingInstalledPkgs(0);
Mayank Garg31e73042020-01-23 00:10:38 -0800443 }
Mayank Garg31e73042020-01-23 00:10:38 -0800444 };
445
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800446 // run from HandlerThread
447 private void doHandleInit() {
Ram Periathiruvadi295954d2018-04-10 18:27:28 -0700448 startAppBlockingPolicies();
Antonio Kantekf7007532020-03-17 10:37:58 -0700449 mUserService.addUserLifecycleListener(mUserLifecycleListener);
Ram Periathiruvadi295954d2018-04-10 18:27:28 -0700450 IntentFilter pkgParseIntent = new IntentFilter();
Ram Periathiruvadi295954d2018-04-10 18:27:28 -0700451 for (String action : mPackageManagerActions) {
452 pkgParseIntent.addAction(action);
453 }
454 pkgParseIntent.addDataScheme("package");
Yao, Yuxing0c6fc732019-05-10 14:58:49 -0700455 mContext.registerReceiverAsUser(mPackageParsingEventReceiver, UserHandle.ALL,
456 pkgParseIntent, null, null);
Yao, Yuxingd525de12019-05-06 15:11:48 -0700457
458 List<Display> physicalDisplays = getPhysicalDisplays();
459
460 // Assume default display (display 0) is always a physical display.
461 Display defaultDisplay = mDisplayManager.getDisplay(Display.DEFAULT_DISPLAY);
462 if (!physicalDisplays.contains(defaultDisplay)) {
463 if (Log.isLoggable(CarLog.TAG_PACKAGE, Log.INFO)) {
Eric Jeong47b1e242020-12-21 13:41:36 -0800464 Slog.i(CarLog.TAG_PACKAGE, "Adding default display to physical displays.");
Yao, Yuxingd525de12019-05-06 15:11:48 -0700465 }
466 physicalDisplays.add(defaultDisplay);
467 }
468 for (Display physicalDisplay : physicalDisplays) {
469 int displayId = physicalDisplay.getDisplayId();
470 UxRestrictionsListener listener = new UxRestrictionsListener(mCarUxRestrictionsService);
471 mUxRestrictionsListeners.put(displayId, listener);
472 mCarUxRestrictionsService.registerUxRestrictionsChangeListener(listener, displayId);
Keun-young Park6dcc50b2016-10-10 19:01:11 -0700473 }
Pavel Maltsev38da4312019-04-08 10:38:38 -0700474 mVendorServiceController.init();
Ram Periathiruvadi38388302018-02-22 16:42:49 -0800475 }
476
477 private void doParseInstalledPackages() {
Yao, Yuxing0c6fc732019-05-10 14:58:49 -0700478 int userId = mActivityManager.getCurrentUser();
Jordan Jozwiak794abcb2020-07-27 08:08:11 -0700479 generateActivityAllowlistMap(userId);
Yan Zhu211b1fe2019-11-06 15:54:19 -0800480 synchronized (mLock) {
Ram Periathiruvadic57678d2018-04-23 09:18:33 -0700481 mHasParsedPackages = true;
482 }
Jordan Jozwiak794abcb2020-07-27 08:08:11 -0700483 // Once the activity launch listener is registered we attempt to block any non-allowlisted
484 // activities that are launched. For this reason, we need to wait until after the allowlist
Jordan Jozwiaka5f10912019-08-22 15:29:01 -0700485 // has been created.
486 mSystemActivityMonitoringService.registerActivityLaunchListener(mActivityLaunchListener);
Yao, Yuxingd525de12019-05-06 15:11:48 -0700487 blockTopActivitiesIfNecessary();
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800488 }
489
Yan Zhu211b1fe2019-11-06 15:54:19 -0800490 private void doHandleRelease() {
491 synchronized (mLock) {
492 mVendorServiceController.release();
493 mLock.notifyAll();
494 }
Keun-young Park6dcc50b2016-10-10 19:01:11 -0700495 }
496
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800497 private void doUpdatePolicy(String packageName, CarAppBlockingPolicy policy, int flags) {
498 if (DBG_POLICY_SET) {
Eric Jeong47b1e242020-12-21 13:41:36 -0800499 Slog.i(CarLog.TAG_PACKAGE, "setting policy from:" + packageName + ",policy:" + policy
500 + ",flags:0x" + Integer.toHexString(flags));
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800501 }
Jordan Jozwiak794abcb2020-07-27 08:08:11 -0700502 AppBlockingPackageInfoWrapper[] blocklistWrapper = verifyList(policy.blacklists);
503 AppBlockingPackageInfoWrapper[] allowlistWrapper = verifyList(policy.whitelists);
Yan Zhu211b1fe2019-11-06 15:54:19 -0800504 synchronized (mLock) {
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800505 ClientPolicy clientPolicy = mClientPolicies.get(packageName);
506 if (clientPolicy == null) {
507 clientPolicy = new ClientPolicy();
508 mClientPolicies.put(packageName, clientPolicy);
509 }
510 if ((flags & CarPackageManager.FLAG_SET_POLICY_ADD) != 0) {
Jordan Jozwiak794abcb2020-07-27 08:08:11 -0700511 clientPolicy.addToBlocklists(blocklistWrapper);
512 clientPolicy.addToAllowlists(allowlistWrapper);
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800513 } else if ((flags & CarPackageManager.FLAG_SET_POLICY_REMOVE) != 0) {
Jordan Jozwiak794abcb2020-07-27 08:08:11 -0700514 clientPolicy.removeBlocklists(blocklistWrapper);
515 clientPolicy.removeAllowlists(allowlistWrapper);
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800516 } else { //replace.
Jordan Jozwiak794abcb2020-07-27 08:08:11 -0700517 clientPolicy.replaceBlocklists(blocklistWrapper);
518 clientPolicy.replaceAllowlists(allowlistWrapper);
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800519 }
520 if ((flags & CarPackageManager.FLAG_SET_POLICY_WAIT_FOR_CHANGE) != 0) {
Keun young Park6c4fd342019-12-13 12:46:04 -0800521 mWaitingPolicies.remove(policy);
Keun young Parkff3196b2020-01-07 12:44:10 -0800522 mLock.notifyAll();
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800523 }
524 if (DBG_POLICY_SET) {
Eric Jeong47b1e242020-12-21 13:41:36 -0800525 Slog.i(CarLog.TAG_PACKAGE, "policy set:" + dumpPoliciesLocked(false));
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800526 }
527 }
Keun-young Park4727da32016-05-31 10:00:51 -0700528 blockTopActivitiesIfNecessary();
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800529 }
530
531 private AppBlockingPackageInfoWrapper[] verifyList(AppBlockingPackageInfo[] list) {
532 if (list == null) {
533 return null;
534 }
535 LinkedList<AppBlockingPackageInfoWrapper> wrappers = new LinkedList<>();
536 for (int i = 0; i < list.length; i++) {
537 AppBlockingPackageInfo info = list[i];
538 if (info == null) {
539 continue;
540 }
541 boolean isMatching = isInstalledPackageMatching(info);
542 wrappers.add(new AppBlockingPackageInfoWrapper(info, isMatching));
543 }
544 return wrappers.toArray(new AppBlockingPackageInfoWrapper[wrappers.size()]);
545 }
546
547 boolean isInstalledPackageMatching(AppBlockingPackageInfo info) {
Yao, Yuxing4ddb2c62019-02-04 11:26:46 -0800548 PackageInfo packageInfo;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800549 try {
550 packageInfo = mPackageManager.getPackageInfo(info.packageName,
551 PackageManager.GET_SIGNATURES);
552 } catch (NameNotFoundException e) {
553 return false;
554 }
555 if (packageInfo == null) {
556 return false;
557 }
558 // if it is system app and client specified the flag, do not check signature
559 if ((info.flags & AppBlockingPackageInfo.FLAG_SYSTEM_APP) == 0 ||
560 (!packageInfo.applicationInfo.isSystemApp() &&
561 !packageInfo.applicationInfo.isUpdatedSystemApp())) {
Yao, Yuxing4ddb2c62019-02-04 11:26:46 -0800562 Signature[] signatures = packageInfo.signatures;
563 if (!isAnySignatureMatching(signatures, info.signatures)) {
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800564 return false;
565 }
566 }
567 int version = packageInfo.versionCode;
568 if (info.minRevisionCode == 0) {
569 if (info.maxRevisionCode == 0) { // all versions
570 return true;
571 } else { // only max version matters
572 return info.maxRevisionCode > version;
573 }
574 } else { // min version matters
575 if (info.maxRevisionCode == 0) {
576 return info.minRevisionCode < version;
577 } else {
578 return (info.minRevisionCode < version) && (info.maxRevisionCode > version);
579 }
580 }
581 }
582
583 /**
584 * Any signature from policy matching with package's signatures is treated as matching.
585 */
586 boolean isAnySignatureMatching(Signature[] fromPackage, Signature[] fromPolicy) {
587 if (fromPackage == null) {
588 return false;
589 }
590 if (fromPolicy == null) {
591 return false;
592 }
593 ArraySet<Signature> setFromPackage = new ArraySet<Signature>();
594 for (Signature sig : fromPackage) {
595 setFromPackage.add(sig);
596 }
597 for (Signature sig : fromPolicy) {
598 if (setFromPackage.contains(sig)) {
599 return true;
600 }
601 }
602 return false;
603 }
604
Keun-young Park4727da32016-05-31 10:00:51 -0700605 /**
Jordan Jozwiak794abcb2020-07-27 08:08:11 -0700606 * Generate a map of allowlisted packages and activities of the form {pkgName, Allowlisted
607 * activities}. The allowlist information can come from a configuration XML resource or from
Ram Periathiruvadi46a3a3d2018-03-23 16:58:32 -0700608 * the apps marking their activities as distraction optimized.
Yao, Yuxing0c6fc732019-05-10 14:58:49 -0700609 *
Jordan Jozwiak794abcb2020-07-27 08:08:11 -0700610 * @param userId Generate allowlist based on packages installed for this user.
Keun-young Park4727da32016-05-31 10:00:51 -0700611 */
Jordan Jozwiak794abcb2020-07-27 08:08:11 -0700612 private void generateActivityAllowlistMap(int userId) {
613 // Get the apps/activities that are allowlisted in the configuration XML resources.
614 Map<String, Set<String>> configAllowlist = generateConfigAllowlist();
615 Map<String, Set<String>> configBlocklist = generateConfigBlocklist();
Yao, Yuxing0c6fc732019-05-10 14:58:49 -0700616
Jordan Jozwiak794abcb2020-07-27 08:08:11 -0700617 Map<String, AppBlockingPackageInfoWrapper> activityAllowlist =
618 generateActivityAllowlistAsUser(UserHandle.USER_SYSTEM,
619 configAllowlist, configBlocklist);
Yao, Yuxing0c6fc732019-05-10 14:58:49 -0700620 // Also parse packages for current user.
621 if (userId != UserHandle.USER_SYSTEM) {
Jordan Jozwiak794abcb2020-07-27 08:08:11 -0700622 Map<String, AppBlockingPackageInfoWrapper> userAllowlistedPackages =
623 generateActivityAllowlistAsUser(userId, configAllowlist, configBlocklist);
624 for (String packageName : userAllowlistedPackages.keySet()) {
625 if (activityAllowlist.containsKey(packageName)) {
Yao, Yuxing0c6fc732019-05-10 14:58:49 -0700626 continue;
627 }
Jordan Jozwiak794abcb2020-07-27 08:08:11 -0700628 activityAllowlist.put(packageName, userAllowlistedPackages.get(packageName));
Yao, Yuxing0c6fc732019-05-10 14:58:49 -0700629 }
630 }
Yan Zhu211b1fe2019-11-06 15:54:19 -0800631 synchronized (mLock) {
Jordan Jozwiak794abcb2020-07-27 08:08:11 -0700632 mActivityAllowlistMap.clear();
633 mActivityAllowlistMap.putAll(activityAllowlist);
Yao, Yuxing0c6fc732019-05-10 14:58:49 -0700634 }
635 }
636
Jordan Jozwiak794abcb2020-07-27 08:08:11 -0700637 private Map<String, Set<String>> generateConfigAllowlist() {
638 Map<String, Set<String>> configAllowlist = new HashMap<>();
Mayank Gargf2534372020-08-05 17:08:17 -0700639 mConfiguredAllowlist = mContext.getString(R.string.activityAllowlist);
Jordan Jozwiak794abcb2020-07-27 08:08:11 -0700640 if (mConfiguredAllowlist == null) {
Ram Periathiruvadie6e2ac32018-05-02 14:57:46 -0700641 if (DBG_POLICY_CHECK) {
Eric Jeong47b1e242020-12-21 13:41:36 -0800642 Slog.w(CarLog.TAG_PACKAGE, "Allowlist is null.");
Ram Periathiruvadie6e2ac32018-05-02 14:57:46 -0700643 }
Ram Periathiruvadie6e2ac32018-05-02 14:57:46 -0700644 }
Jordan Jozwiak794abcb2020-07-27 08:08:11 -0700645 parseConfigList(mConfiguredAllowlist, configAllowlist);
Yao, Yuxing0c6fc732019-05-10 14:58:49 -0700646
Mayank Gargf2534372020-08-05 17:08:17 -0700647 mConfiguredSystemAllowlist = mContext.getString(R.string.systemActivityAllowlist);
Jordan Jozwiak794abcb2020-07-27 08:08:11 -0700648 if (mConfiguredSystemAllowlist == null) {
Yao, Yuxing4c3b93c2019-02-20 09:00:01 -0800649 if (DBG_POLICY_CHECK) {
Eric Jeong47b1e242020-12-21 13:41:36 -0800650 Slog.w(CarLog.TAG_PACKAGE, "System allowlist is null.");
Yao, Yuxing4c3b93c2019-02-20 09:00:01 -0800651 }
652 }
Jordan Jozwiak794abcb2020-07-27 08:08:11 -0700653 parseConfigList(mConfiguredSystemAllowlist, configAllowlist);
Yao, Yuxing4c3b93c2019-02-20 09:00:01 -0800654
Jordan Jozwiak794abcb2020-07-27 08:08:11 -0700655 // Add the blocking overlay activity to the allowlist, since that needs to run in a
Ram Periathiruvadi46a3a3d2018-03-23 16:58:32 -0700656 // restricted state to communicate the reason an app was blocked.
Keun-young Park4727da32016-05-31 10:00:51 -0700657 Set<String> defaultActivity = new ArraySet<>();
Ram Periathiruvadi402d12e2018-07-11 18:31:13 -0700658 if (mActivityBlockingActivity != null) {
659 defaultActivity.add(mActivityBlockingActivity.getClassName());
Jordan Jozwiak794abcb2020-07-27 08:08:11 -0700660 configAllowlist.put(mActivityBlockingActivity.getPackageName(), defaultActivity);
Ram Periathiruvadi402d12e2018-07-11 18:31:13 -0700661 }
Ram Periathiruvadi38388302018-02-22 16:42:49 -0800662
Jordan Jozwiak794abcb2020-07-27 08:08:11 -0700663 return configAllowlist;
Yao, Yuxing0c6fc732019-05-10 14:58:49 -0700664 }
665
Jordan Jozwiak794abcb2020-07-27 08:08:11 -0700666 private Map<String, Set<String>> generateConfigBlocklist() {
667 Map<String, Set<String>> configBlocklist = new HashMap<>();
Mayank Gargf2534372020-08-05 17:08:17 -0700668 mConfiguredBlocklist = mContext.getString(R.string.activityDenylist);
Jordan Jozwiak794abcb2020-07-27 08:08:11 -0700669 if (mConfiguredBlocklist == null) {
Yao, Yuxing0c6fc732019-05-10 14:58:49 -0700670 if (DBG_POLICY_CHECK) {
Eric Jeong47b1e242020-12-21 13:41:36 -0800671 Slog.d(CarLog.TAG_PACKAGE, "Null blocklist in config");
Yao, Yuxing0c6fc732019-05-10 14:58:49 -0700672 }
673 }
Jordan Jozwiak794abcb2020-07-27 08:08:11 -0700674 parseConfigList(mConfiguredBlocklist, configBlocklist);
Yao, Yuxing0c6fc732019-05-10 14:58:49 -0700675
Jordan Jozwiak794abcb2020-07-27 08:08:11 -0700676 return configBlocklist;
Yao, Yuxing0c6fc732019-05-10 14:58:49 -0700677 }
678
679 /**
Jordan Jozwiak794abcb2020-07-27 08:08:11 -0700680 * Generates allowlisted activities based on packages installed for system user and current
681 * user (if different). Factors affecting allowlist:
682 * - allowlist from resource config;
Yao, Yuxing0c6fc732019-05-10 14:58:49 -0700683 * - activity declared as Distraction Optimized (D.O.) in manifest;
Jordan Jozwiak794abcb2020-07-27 08:08:11 -0700684 * - blocklist from resource config - package/activity blocklisted will not exist
685 * in returned allowlist.
Yao, Yuxing0c6fc732019-05-10 14:58:49 -0700686 *
Jordan Jozwiak12d59e02019-06-20 18:10:21 -0700687 * @param userId Parse packages installed for user.
Jordan Jozwiak794abcb2020-07-27 08:08:11 -0700688 * @param configAllowlist Allowlist from config.
689 * @param configBlocklist Blocklist from config.
Yao, Yuxing0c6fc732019-05-10 14:58:49 -0700690 */
Jordan Jozwiak794abcb2020-07-27 08:08:11 -0700691 private Map<String, AppBlockingPackageInfoWrapper> generateActivityAllowlistAsUser(int userId,
692 Map<String, Set<String>> configAllowlist, Map<String, Set<String>> configBlocklist) {
693 HashMap<String, AppBlockingPackageInfoWrapper> activityAllowlist = new HashMap<>();
Yao, Yuxing0c6fc732019-05-10 14:58:49 -0700694
Mayank Garg31e73042020-01-23 00:10:38 -0800695 List<PackageInfo> packages = mPackageManager
696 .getInstalledPackagesAsUser(PackageManager.GET_SIGNATURES
697 | PackageManager.GET_ACTIVITIES | PackageManager.MATCH_DIRECT_BOOT_AWARE
698 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userId);
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800699 for (PackageInfo info : packages) {
Ram Periathiruvadi38388302018-02-22 16:42:49 -0800700 if (info.applicationInfo == null) {
701 continue;
702 }
703
704 int flags = 0;
Yao, Yuxing2a1e1d92019-01-08 11:58:52 -0800705 Set<String> activities = new ArraySet<>();
Ram Periathiruvadi38388302018-02-22 16:42:49 -0800706
707 if (info.applicationInfo.isSystemApp()
708 || info.applicationInfo.isUpdatedSystemApp()) {
709 flags = AppBlockingPackageInfo.FLAG_SYSTEM_APP;
710 }
711
Jordan Jozwiak794abcb2020-07-27 08:08:11 -0700712 /* 1. Check if all or some of this app is in the <activityAllowlist> or
713 <systemActivityAllowlist> in config.xml */
714 Set<String> configActivitiesForPackage = configAllowlist.get(info.packageName);
Ram Periathiruvadi38388302018-02-22 16:42:49 -0800715 if (configActivitiesForPackage != null) {
716 if (DBG_POLICY_CHECK) {
Eric Jeong47b1e242020-12-21 13:41:36 -0800717 Slog.d(CarLog.TAG_PACKAGE, info.packageName + " allowlisted");
Ram Periathiruvadi38388302018-02-22 16:42:49 -0800718 }
719 if (configActivitiesForPackage.size() == 0) {
Jordan Jozwiak794abcb2020-07-27 08:08:11 -0700720 // Whole Pkg has been allowlisted
Ram Periathiruvadi38388302018-02-22 16:42:49 -0800721 flags |= AppBlockingPackageInfo.FLAG_WHOLE_ACTIVITY;
Jordan Jozwiak794abcb2020-07-27 08:08:11 -0700722 // Add all activities to the allowlist
Yao, Yuxing2a1e1d92019-01-08 11:58:52 -0800723 List<String> activitiesForPackage = getActivitiesInPackage(info);
724 if (activitiesForPackage != null) {
725 activities.addAll(activitiesForPackage);
726 } else {
727 if (DBG_POLICY_CHECK) {
Eric Jeong47b1e242020-12-21 13:41:36 -0800728 Slog.d(CarLog.TAG_PACKAGE, info.packageName + ": Activities null");
Yao, Yuxing2a1e1d92019-01-08 11:58:52 -0800729 }
Keun-young Park4727da32016-05-31 10:00:51 -0700730 }
731 } else {
Ram Periathiruvadi38388302018-02-22 16:42:49 -0800732 if (DBG_POLICY_CHECK) {
Eric Jeong47b1e242020-12-21 13:41:36 -0800733 Slog.d(CarLog.TAG_PACKAGE, "Partially Allowlisted. WL Activities:");
Ram Periathiruvadi38388302018-02-22 16:42:49 -0800734 for (String a : configActivitiesForPackage) {
Eric Jeong47b1e242020-12-21 13:41:36 -0800735 Slog.d(CarLog.TAG_PACKAGE, a);
Keun-young Park4727da32016-05-31 10:00:51 -0700736 }
737 }
Yao, Yuxing2a1e1d92019-01-08 11:58:52 -0800738 activities.addAll(configActivitiesForPackage);
Ram Periathiruvadi38388302018-02-22 16:42:49 -0800739 }
Yao, Yuxing2a1e1d92019-01-08 11:58:52 -0800740 }
741 /* 2. If app is not listed in the config.xml check their Manifest meta-data to
742 see if they have any Distraction Optimized(DO) activities.
743 For non system apps, we check if the app install source was a permittable
744 source. This prevents side-loaded apps to fake DO. Bypass the check
745 for debug builds for development convenience. */
746 if (!isDebugBuild()
747 && !info.applicationInfo.isSystemApp()
748 && !info.applicationInfo.isUpdatedSystemApp()) {
Ram Periathiruvadi38388302018-02-22 16:42:49 -0800749 try {
Yao, Yuxing2a1e1d92019-01-08 11:58:52 -0800750 if (mAllowedAppInstallSources != null) {
751 String installerName = mPackageManager.getInstallerPackageName(
752 info.packageName);
753 if (installerName == null || (installerName != null
754 && !mAllowedAppInstallSources.contains(installerName))) {
Eric Jeong47b1e242020-12-21 13:41:36 -0800755 Slog.w(CarLog.TAG_PACKAGE,
Yao, Yuxing2a1e1d92019-01-08 11:58:52 -0800756 info.packageName + " not installed from permitted sources "
Oleh Cherpak01b09332019-02-12 15:43:33 +0200757 + (installerName == null ? "NULL" : installerName));
Yao, Yuxing2a1e1d92019-01-08 11:58:52 -0800758 continue;
759 }
760 }
761 } catch (IllegalArgumentException e) {
Eric Jeong47b1e242020-12-21 13:41:36 -0800762 Slog.w(CarLog.TAG_PACKAGE, info.packageName + " not installed!");
Ram Periathiruvadi38388302018-02-22 16:42:49 -0800763 continue;
764 }
Yao, Yuxing2a1e1d92019-01-08 11:58:52 -0800765 }
766
767 try {
Yao, Yuxing0c6fc732019-05-10 14:58:49 -0700768 String[] doActivities =
769 CarAppMetadataReader.findDistractionOptimizedActivitiesAsUser(
770 mContext, info.packageName, userId);
Yao, Yuxing2a1e1d92019-01-08 11:58:52 -0800771 if (doActivities != null) {
Ram Periathiruvadi38388302018-02-22 16:42:49 -0800772 // Some of the activities in this app are Distraction Optimized.
773 if (DBG_POLICY_CHECK) {
Yao, Yuxing2a1e1d92019-01-08 11:58:52 -0800774 for (String activity : doActivities) {
Eric Jeong47b1e242020-12-21 13:41:36 -0800775 Slog.d(CarLog.TAG_PACKAGE, "adding " + activity + " from "
Jordan Jozwiak794abcb2020-07-27 08:08:11 -0700776 + info.packageName + " to allowlist");
Ram Periathiruvadi38388302018-02-22 16:42:49 -0800777 }
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800778 }
Yao, Yuxing2a1e1d92019-01-08 11:58:52 -0800779 activities.addAll(Arrays.asList(doActivities));
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800780 }
Yao, Yuxing2a1e1d92019-01-08 11:58:52 -0800781 } catch (NameNotFoundException e) {
Eric Jeong47b1e242020-12-21 13:41:36 -0800782 Slog.w(CarLog.TAG_PACKAGE, "Error reading metadata: " + info.packageName);
Yao, Yuxing2a1e1d92019-01-08 11:58:52 -0800783 continue;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800784 }
Yao, Yuxing2a1e1d92019-01-08 11:58:52 -0800785
Jordan Jozwiak794abcb2020-07-27 08:08:11 -0700786 // Nothing to add to allowlist
Yao, Yuxing2a1e1d92019-01-08 11:58:52 -0800787 if (activities.isEmpty()) {
Ram Periathiruvadi38388302018-02-22 16:42:49 -0800788 continue;
789 }
790
Jordan Jozwiak794abcb2020-07-27 08:08:11 -0700791 /* 3. Check if parsed activity is in <activityBlocklist> in config.xml. Anything
792 in blocklist should not be allowlisted, either as D.O. or by config. */
793 if (configBlocklist.containsKey(info.packageName)) {
794 Set<String> configBlocklistActivities = configBlocklist.get(info.packageName);
795 if (configBlocklistActivities.isEmpty()) {
796 // Whole package should be blocklisted.
Yao, Yuxing0c6fc732019-05-10 14:58:49 -0700797 continue;
798 }
Jordan Jozwiak794abcb2020-07-27 08:08:11 -0700799 activities.removeAll(configBlocklistActivities);
Yao, Yuxing0c6fc732019-05-10 14:58:49 -0700800 }
801
Ram Periathiruvadi38388302018-02-22 16:42:49 -0800802 Signature[] signatures;
803 signatures = info.signatures;
804 AppBlockingPackageInfo appBlockingInfo = new AppBlockingPackageInfo(
Yao, Yuxing2a1e1d92019-01-08 11:58:52 -0800805 info.packageName, 0, 0, flags, signatures,
806 activities.toArray(new String[activities.size()]));
Ram Periathiruvadi38388302018-02-22 16:42:49 -0800807 AppBlockingPackageInfoWrapper wrapper = new AppBlockingPackageInfoWrapper(
808 appBlockingInfo, true);
Jordan Jozwiak794abcb2020-07-27 08:08:11 -0700809 activityAllowlist.put(info.packageName, wrapper);
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800810 }
Jordan Jozwiak794abcb2020-07-27 08:08:11 -0700811 return activityAllowlist;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800812 }
813
Ram Periathiruvadid937c322018-06-13 12:28:12 -0700814 private boolean isDebugBuild() {
815 return Build.IS_USERDEBUG || Build.IS_ENG;
816 }
817
Ram Periathiruvadi46a3a3d2018-03-23 16:58:32 -0700818 /**
Yao, Yuxing4c3b93c2019-02-20 09:00:01 -0800819 * Parses the given resource and updates the input map of packages and activities.
820 *
821 * Key is package name and value is list of activities. Empty set implies whole package is
Ram Periathiruvadi46a3a3d2018-03-23 16:58:32 -0700822 * included.
Yao, Yuxing4c3b93c2019-02-20 09:00:01 -0800823 *
824 * When there are multiple entries regarding one package, the entry with
Jordan Jozwiak794abcb2020-07-27 08:08:11 -0700825 * greater scope wins. Namely if there were 2 entries such that one allowlists
826 * an activity, and the other allowlists the entire package of the activity,
827 * the package is allowlisted, regardless of input order.
Ram Periathiruvadi46a3a3d2018-03-23 16:58:32 -0700828 */
Yao, Yuxing4c3b93c2019-02-20 09:00:01 -0800829 @VisibleForTesting
830 /* package */ void parseConfigList(String configList,
831 @NonNull Map<String, Set<String>> packageToActivityMap) {
Ram Periathiruvadie6e2ac32018-05-02 14:57:46 -0700832 if (configList == null) {
Yao, Yuxing4c3b93c2019-02-20 09:00:01 -0800833 return;
Ram Periathiruvadie6e2ac32018-05-02 14:57:46 -0700834 }
Ram Periathiruvadi46a3a3d2018-03-23 16:58:32 -0700835 String[] entries = configList.split(PACKAGE_DELIMITER);
836 for (String entry : entries) {
837 String[] packageActivityPair = entry.split(PACKAGE_ACTIVITY_DELIMITER);
838 Set<String> activities = packageToActivityMap.get(packageActivityPair[0]);
839 boolean newPackage = false;
840 if (activities == null) {
841 activities = new ArraySet<>();
842 newPackage = true;
843 packageToActivityMap.put(packageActivityPair[0], activities);
844 }
845 if (packageActivityPair.length == 1) { // whole package
846 activities.clear();
847 } else if (packageActivityPair.length == 2) {
Jordan Jozwiak794abcb2020-07-27 08:08:11 -0700848 // add class name only when the whole package is not allowlisted.
Ram Periathiruvadi46a3a3d2018-03-23 16:58:32 -0700849 if (newPackage || (activities.size() > 0)) {
850 activities.add(packageActivityPair[1]);
851 }
852 }
853 }
Ram Periathiruvadi46a3a3d2018-03-23 16:58:32 -0700854 }
855
Ram Periathiruvadi38388302018-02-22 16:42:49 -0800856 @Nullable
Yao, Yuxing2a1e1d92019-01-08 11:58:52 -0800857 private List<String> getActivitiesInPackage(PackageInfo info) {
Ram Periathiruvadi38388302018-02-22 16:42:49 -0800858 if (info == null || info.activities == null) {
859 return null;
860 }
861 List<String> activityList = new ArrayList<>();
862 for (ActivityInfo aInfo : info.activities) {
863 activityList.add(aInfo.name);
864 }
Yao, Yuxing2a1e1d92019-01-08 11:58:52 -0800865 return activityList;
Ram Periathiruvadi38388302018-02-22 16:42:49 -0800866 }
867
Ram Periathiruvadi8ef1a202018-03-16 17:49:21 -0700868 /**
869 * Checks if there are any {@link CarAppBlockingPolicyService} and creates a proxy to
870 * bind to them and retrieve the {@link CarAppBlockingPolicy}
871 */
872 @VisibleForTesting
873 public void startAppBlockingPolicies() {
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800874 Intent policyIntent = new Intent();
875 policyIntent.setAction(CarAppBlockingPolicyService.SERVICE_INTERFACE);
876 List<ResolveInfo> policyInfos = mPackageManager.queryIntentServices(policyIntent, 0);
877 if (policyInfos == null) { //no need to wait for service binding and retrieval.
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800878 return;
879 }
880 LinkedList<AppBlockingPolicyProxy> proxies = new LinkedList<>();
881 for (ResolveInfo resolveInfo : policyInfos) {
882 ServiceInfo serviceInfo = resolveInfo.serviceInfo;
883 if (serviceInfo == null) {
884 continue;
885 }
886 if (serviceInfo.isEnabled()) {
887 if (mPackageManager.checkPermission(Car.PERMISSION_CONTROL_APP_BLOCKING,
888 serviceInfo.packageName) != PackageManager.PERMISSION_GRANTED) {
889 continue;
890 }
Eric Jeong47b1e242020-12-21 13:41:36 -0800891 Slog.i(CarLog.TAG_PACKAGE, "found policy holding service:" + serviceInfo);
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800892 AppBlockingPolicyProxy proxy = new AppBlockingPolicyProxy(this, mContext,
893 serviceInfo);
894 proxy.connect();
895 proxies.add(proxy);
896 }
897 }
Yan Zhu211b1fe2019-11-06 15:54:19 -0800898 synchronized (mLock) {
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800899 mProxies = proxies;
900 }
901 }
902
903 public void onPolicyConnectionAndSet(AppBlockingPolicyProxy proxy,
904 CarAppBlockingPolicy policy) {
905 doHandlePolicyConnection(proxy, policy);
906 }
907
908 public void onPolicyConnectionFailure(AppBlockingPolicyProxy proxy) {
909 doHandlePolicyConnection(proxy, null);
910 }
911
912 private void doHandlePolicyConnection(AppBlockingPolicyProxy proxy,
913 CarAppBlockingPolicy policy) {
Yan Zhu211b1fe2019-11-06 15:54:19 -0800914 synchronized (mLock) {
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800915 if (mProxies == null) {
916 proxy.disconnect();
917 return;
918 }
919 mProxies.remove(proxy);
920 if (mProxies.size() == 0) {
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800921 mProxies = null;
922 }
923 }
924 try {
925 if (policy != null) {
926 if (DBG_POLICY_SET) {
Eric Jeong47b1e242020-12-21 13:41:36 -0800927 Slog.i(CarLog.TAG_PACKAGE, "policy setting from policy service:"
928 + proxy.getPackageName());
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800929 }
Keun young Park6c4fd342019-12-13 12:46:04 -0800930 doSetAppBlockingPolicy(proxy.getPackageName(), policy, 0);
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800931 }
932 } finally {
933 proxy.disconnect();
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800934 }
935 }
936
937 @Override
938 public void dump(PrintWriter writer) {
Yan Zhu211b1fe2019-11-06 15:54:19 -0800939 synchronized (mLock) {
Jordan Jozwiak0aa05982019-06-17 15:14:39 -0700940 writer.println("*CarPackageManagerService*");
Keun-young Park4727da32016-05-31 10:00:51 -0700941 writer.println("mEnableActivityBlocking:" + mEnableActivityBlocking);
Ram Periathiruvadie6e2ac32018-05-02 14:57:46 -0700942 writer.println("mHasParsedPackages:" + mHasParsedPackages);
Yao, Yuxingd525de12019-05-06 15:11:48 -0700943 List<String> restrictions = new ArrayList<>(mUxRestrictionsListeners.size());
944 for (int i = 0; i < mUxRestrictionsListeners.size(); i++) {
945 int displayId = mUxRestrictionsListeners.keyAt(i);
946 UxRestrictionsListener listener = mUxRestrictionsListeners.valueAt(i);
947 restrictions.add(String.format("Display %d is %s",
948 displayId, (listener.isRestricted() ? "restricted" : "unrestricted")));
949 }
950 writer.println("Display Restrictions:\n" + String.join("\n", restrictions));
Jordan Jozwiak0aa05982019-06-17 15:14:39 -0700951 writer.println(" Blocked activity log:");
Yao, Yuxingd1d6a372018-05-08 10:37:43 -0700952 writer.println(String.join("\n", mBlockedActivityLogs));
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800953 writer.print(dumpPoliciesLocked(true));
954 }
955 }
956
Yan Zhu211b1fe2019-11-06 15:54:19 -0800957 @GuardedBy("mLock")
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800958 private String dumpPoliciesLocked(boolean dumpAll) {
959 StringBuilder sb = new StringBuilder();
960 if (dumpAll) {
Jordan Jozwiak794abcb2020-07-27 08:08:11 -0700961 sb.append("**System allowlist**\n");
962 for (AppBlockingPackageInfoWrapper wrapper : mActivityAllowlistMap.values()) {
Ram Periathiruvadi46a3a3d2018-03-23 16:58:32 -0700963 sb.append(wrapper.toString() + "\n");
964 }
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800965 }
966 sb.append("**Client Policies**\n");
967 for (Entry<String, ClientPolicy> entry : mClientPolicies.entrySet()) {
968 sb.append("Client:" + entry.getKey() + "\n");
Jordan Jozwiak794abcb2020-07-27 08:08:11 -0700969 sb.append(" allowlists:\n");
970 for (AppBlockingPackageInfoWrapper wrapper : entry.getValue().mAllowlistsMap.values()) {
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800971 sb.append(wrapper.toString() + "\n");
972 }
Jordan Jozwiak794abcb2020-07-27 08:08:11 -0700973 sb.append(" blocklists:\n");
974 for (AppBlockingPackageInfoWrapper wrapper : entry.getValue().mBlocklistsMap.values()) {
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800975 sb.append(wrapper.toString() + "\n");
976 }
977 }
978 sb.append("**Unprocessed policy services**\n");
979 if (mProxies != null) {
980 for (AppBlockingPolicyProxy proxy : mProxies) {
981 sb.append(proxy.toString() + "\n");
982 }
983 }
Jordan Jozwiak794abcb2020-07-27 08:08:11 -0700984 sb.append("**Allowlist string in resource**\n");
985 sb.append(mConfiguredAllowlist + "\n");
Ram Periathiruvadi46a3a3d2018-03-23 16:58:32 -0700986
Jordan Jozwiak794abcb2020-07-27 08:08:11 -0700987 sb.append("**System allowlist string in resource**\n");
988 sb.append(mConfiguredSystemAllowlist + "\n");
Yao, Yuxing0c6fc732019-05-10 14:58:49 -0700989
Jordan Jozwiak794abcb2020-07-27 08:08:11 -0700990 sb.append("**Blocklist string in resource**\n");
991 sb.append(mConfiguredBlocklist + "\n");
Keun-young Park98960812016-10-04 12:50:54 -0700992
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800993 return sb.toString();
994 }
995
Yao, Yuxingd525de12019-05-06 15:11:48 -0700996 /**
997 * Returns display with physical address.
998 */
999 private List<Display> getPhysicalDisplays() {
1000 List<Display> displays = new ArrayList<>();
1001 for (Display display : mDisplayManager.getDisplays()) {
1002 if (display.getAddress() instanceof DisplayAddress.Physical) {
1003 displays.add(display);
1004 }
1005 }
1006 return displays;
1007 }
1008
1009 /**
1010 * Returns whether UX restrictions is required for display.
1011 *
1012 * Non-physical display will use restrictions for {@link Display#DEFAULT_DISPLAY}.
1013 */
1014 private boolean isUxRestrictedOnDisplay(int displayId) {
1015 UxRestrictionsListener listenerForTopTaskDisplay;
1016 if (mUxRestrictionsListeners.indexOfKey(displayId) < 0) {
1017 listenerForTopTaskDisplay = mUxRestrictionsListeners.get(Display.DEFAULT_DISPLAY);
1018 if (listenerForTopTaskDisplay == null) {
1019 // This should never happen.
Eric Jeong47b1e242020-12-21 13:41:36 -08001020 Slog.e(CarLog.TAG_PACKAGE, "Missing listener for default display.");
Yao, Yuxingd525de12019-05-06 15:11:48 -07001021 return true;
1022 }
1023 } else {
1024 listenerForTopTaskDisplay = mUxRestrictionsListeners.get(displayId);
1025 }
1026
1027 return listenerForTopTaskDisplay.isRestricted();
1028 }
1029
1030 private void blockTopActivitiesIfNecessary() {
1031 List<TopTaskInfoContainer> topTasks = mSystemActivityMonitoringService.getTopTasks();
1032 for (TopTaskInfoContainer topTask : topTasks) {
1033 if (topTask == null) {
Eric Jeong47b1e242020-12-21 13:41:36 -08001034 Slog.e(CarLog.TAG_PACKAGE, "Top tasks contains null.");
Yao, Yuxingd525de12019-05-06 15:11:48 -07001035 continue;
1036 }
1037 blockTopActivityIfNecessary(topTask);
1038 }
1039 }
1040
Keun-young Park4727da32016-05-31 10:00:51 -07001041 private void blockTopActivityIfNecessary(TopTaskInfoContainer topTask) {
Yao, Yuxingd525de12019-05-06 15:11:48 -07001042 if (isUxRestrictedOnDisplay(topTask.displayId)) {
1043 doBlockTopActivityIfNotAllowed(topTask);
Yao, Yuxingcfcc59f2019-03-05 16:35:47 -08001044 }
Keun-young Park4727da32016-05-31 10:00:51 -07001045 }
1046
1047 private void doBlockTopActivityIfNotAllowed(TopTaskInfoContainer topTask) {
Ram Periathiruvadi2da6d0e2018-01-26 18:02:10 -08001048 if (topTask.topActivity == null) {
1049 return;
1050 }
Jordan Jozwiaka5f10912019-08-22 15:29:01 -07001051
1052 // We are not handling the UI blocking until we know what is allowed and what is not.
1053 if (!mHasParsedPackages) {
1054 if (Log.isLoggable(CarLog.TAG_PACKAGE, Log.INFO)) {
Eric Jeong47b1e242020-12-21 13:41:36 -08001055 Slog.i(CarLog.TAG_PACKAGE, "Packages not parsed, so ignoring block for " + topTask);
Jordan Jozwiaka5f10912019-08-22 15:29:01 -07001056 }
1057 return;
1058 }
1059
Ram Periathiruvadie154f582018-03-21 21:53:27 -07001060 boolean allowed = isActivityDistractionOptimized(
Keun-young Park4727da32016-05-31 10:00:51 -07001061 topTask.topActivity.getPackageName(),
1062 topTask.topActivity.getClassName());
1063 if (DBG_POLICY_ENFORCEMENT) {
Eric Jeong47b1e242020-12-21 13:41:36 -08001064 Slog.i(CarLog.TAG_PACKAGE, "new activity:" + topTask.toString() + " allowed:"
1065 + allowed);
Keun-young Park4727da32016-05-31 10:00:51 -07001066 }
Ram Periathiruvadibf0eab72018-02-06 12:32:43 -08001067 if (allowed) {
1068 return;
1069 }
Yan Zhu211b1fe2019-11-06 15:54:19 -08001070 synchronized (mLock) {
Ram Periathiruvadibf0eab72018-02-06 12:32:43 -08001071 if (!mEnableActivityBlocking) {
Eric Jeong47b1e242020-12-21 13:41:36 -08001072 Slog.d(CarLog.TAG_PACKAGE, "Current activity " + topTask.topActivity
1073 + " not allowed, blocking disabled. Number of tasks in stack:"
Louis Chang3bf2f202020-08-18 13:04:28 +08001074 + topTask.taskInfo.childTaskIds.length);
Ram Periathiruvadibf0eab72018-02-06 12:32:43 -08001075 return;
1076 }
1077 }
Yao, Yuxing4ddb2c62019-02-04 11:26:46 -08001078 if (DBG_POLICY_ENFORCEMENT) {
Eric Jeong47b1e242020-12-21 13:41:36 -08001079 Slog.i(CarLog.TAG_PACKAGE, "Current activity " + topTask.topActivity
1080 + " not allowed, will block, number of tasks in stack:"
1081 + topTask.taskInfo.childTaskIds.length);
Keun-young Park4727da32016-05-31 10:00:51 -07001082 }
Yao, Yuxingd1d6a372018-05-08 10:37:43 -07001083
Yao, Yuxing14e83b42018-10-29 18:29:56 -07001084 // Figure out the root activity of blocked task.
1085 String taskRootActivity = null;
Louis Chang3bf2f202020-08-18 13:04:28 +08001086 for (int i = 0; i < topTask.taskInfo.childTaskIds.length; i++) {
Yao, Yuxingd1d6a372018-05-08 10:37:43 -07001087 // topTask.taskId is the task that should be blocked.
Louis Chang3bf2f202020-08-18 13:04:28 +08001088 if (topTask.taskInfo.childTaskIds[i] == topTask.taskId) {
Yao, Yuxingd1d6a372018-05-08 10:37:43 -07001089 // stackInfo represents an ActivityStack. Its fields taskIds and taskNames
1090 // are 1:1 mapped, where taskNames is the name of root activity in this task.
Louis Chang3bf2f202020-08-18 13:04:28 +08001091 taskRootActivity = topTask.taskInfo.childTaskNames[i];
Yao, Yuxingd1d6a372018-05-08 10:37:43 -07001092 break;
1093 }
1094 }
Yao, Yuxing14e83b42018-10-29 18:29:56 -07001095
1096 boolean isRootDO = false;
1097 if (taskRootActivity != null) {
1098 ComponentName componentName = ComponentName.unflattenFromString(taskRootActivity);
1099 isRootDO = isActivityDistractionOptimized(
1100 componentName.getPackageName(), componentName.getClassName());
1101 }
1102
1103 Intent newActivityIntent = createBlockingActivityIntent(
Yao, Yuxingd525de12019-05-06 15:11:48 -07001104 mActivityBlockingActivity, topTask.displayId,
1105 topTask.topActivity.flattenToShortString(), topTask.taskId, taskRootActivity,
1106 isRootDO);
Yao, Yuxing14e83b42018-10-29 18:29:56 -07001107
1108 // Intent contains all info to debug what is blocked - log into both logcat and dumpsys.
1109 String log = "Starting blocking activity with intent: " + newActivityIntent.toUri(0);
1110 if (Log.isLoggable(CarLog.TAG_PACKAGE, Log.INFO)) {
Eric Jeong47b1e242020-12-21 13:41:36 -08001111 Slog.i(CarLog.TAG_PACKAGE, log);
Yao, Yuxing14e83b42018-10-29 18:29:56 -07001112 }
1113 addLog(log);
Ram Periathiruvadi38388302018-02-22 16:42:49 -08001114 mSystemActivityMonitoringService.blockActivity(topTask, newActivityIntent);
Keun-young Park4727da32016-05-31 10:00:51 -07001115 }
1116
Yao, Yuxing14e83b42018-10-29 18:29:56 -07001117 /**
1118 * Creates an intent to start blocking activity.
1119 *
1120 * @param blockingActivity the activity to launch
Jordan Jozwiak12d59e02019-06-20 18:10:21 -07001121 * @param blockedActivity the activity being blocked
1122 * @param blockedTaskId the blocked task id, which contains the blocked activity
Yao, Yuxing14e83b42018-10-29 18:29:56 -07001123 * @param taskRootActivity root activity of the blocked task
Yao, Yuxing14e83b42018-10-29 18:29:56 -07001124 * @return an intent to launch the blocking activity.
1125 */
1126 private static Intent createBlockingActivityIntent(ComponentName blockingActivity,
Yao, Yuxingd525de12019-05-06 15:11:48 -07001127 int displayId, String blockedActivity, int blockedTaskId, String taskRootActivity,
1128 boolean isRootDo) {
Yao, Yuxing14e83b42018-10-29 18:29:56 -07001129 Intent newActivityIntent = new Intent();
Yao, Yuxingd525de12019-05-06 15:11:48 -07001130 newActivityIntent.setFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
Yao, Yuxing14e83b42018-10-29 18:29:56 -07001131 newActivityIntent.setComponent(blockingActivity);
1132 newActivityIntent.putExtra(
Yao, Yuxingd525de12019-05-06 15:11:48 -07001133 BLOCKING_INTENT_EXTRA_DISPLAY_ID, displayId);
1134 newActivityIntent.putExtra(
Yao, Yuxing14e83b42018-10-29 18:29:56 -07001135 BLOCKING_INTENT_EXTRA_BLOCKED_ACTIVITY_NAME, blockedActivity);
1136 newActivityIntent.putExtra(
1137 BLOCKING_INTENT_EXTRA_BLOCKED_TASK_ID, blockedTaskId);
1138 newActivityIntent.putExtra(
1139 BLOCKING_INTENT_EXTRA_ROOT_ACTIVITY_NAME, taskRootActivity);
1140 newActivityIntent.putExtra(
1141 BLOCKING_INTENT_EXTRA_IS_ROOT_ACTIVITY_DO, isRootDo);
Yao, Yuxingcfcc59f2019-03-05 16:35:47 -08001142
Yao, Yuxing14e83b42018-10-29 18:29:56 -07001143 return newActivityIntent;
1144 }
1145
Ram Periathiruvadicdee1202018-07-17 18:01:31 -07001146 /**
1147 * Enable/Disable activity blocking by correspondingly enabling/disabling broadcasting UXR
1148 * changes in {@link CarUxRestrictionsManagerService}. This is only available in
1149 * engineering builds for development convenience.
Ram Periathiruvadicdee1202018-07-17 18:01:31 -07001150 */
Ram Periathiruvadia6e0d9b2018-04-25 20:19:22 -07001151 @Override
Yan Zhu211b1fe2019-11-06 15:54:19 -08001152 public void setEnableActivityBlocking(boolean enable) {
Ram Periathiruvadicdee1202018-07-17 18:01:31 -07001153 if (!isDebugBuild()) {
Eric Jeong47b1e242020-12-21 13:41:36 -08001154 Slog.e(CarLog.TAG_PACKAGE, "Cannot enable/disable activity blocking");
Ram Periathiruvadicdee1202018-07-17 18:01:31 -07001155 return;
1156 }
Yan Zhu211b1fe2019-11-06 15:54:19 -08001157
Ram Periathiruvadia6e0d9b2018-04-25 20:19:22 -07001158 // Check if the caller has the same signature as that of the car service.
1159 if (mPackageManager.checkSignatures(Process.myUid(), Binder.getCallingUid())
1160 != PackageManager.SIGNATURE_MATCH) {
1161 throw new SecurityException(
1162 "Caller " + mPackageManager.getNameForUid(Binder.getCallingUid())
Mayank Garg31e73042020-01-23 00:10:38 -08001163 + " does not have the right signature");
Ram Periathiruvadia6e0d9b2018-04-25 20:19:22 -07001164 }
Ram Periathiruvadicdee1202018-07-17 18:01:31 -07001165 mCarUxRestrictionsService.setUxRChangeBroadcastEnabled(enable);
Ram Periathiruvadibf0eab72018-02-06 12:32:43 -08001166 }
1167
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001168 /**
Ram Periathiruvadi38388302018-02-22 16:42:49 -08001169 * Get the distraction optimized activities for the given package.
1170 *
1171 * @param pkgName Name of the package
1172 * @return Array of the distraction optimized activities in the package
1173 */
1174 @Nullable
1175 public String[] getDistractionOptimizedActivities(String pkgName) {
1176 try {
Yao, Yuxing0c6fc732019-05-10 14:58:49 -07001177 return CarAppMetadataReader.findDistractionOptimizedActivitiesAsUser(mContext, pkgName,
1178 mActivityManager.getCurrentUser());
Ram Periathiruvadi38388302018-02-22 16:42:49 -08001179 } catch (NameNotFoundException e) {
1180 return null;
1181 }
1182 }
Ram Periathiruvadie6e2ac32018-05-02 14:57:46 -07001183
Ram Periathiruvadi38388302018-02-22 16:42:49 -08001184 /**
Yao, Yuxingd1d6a372018-05-08 10:37:43 -07001185 * Append one line of log for dumpsys.
1186 *
1187 * <p>Maintains the size of log by {@link #LOG_SIZE} and appends tag and timestamp to the line.
1188 */
1189 private void addLog(String log) {
1190 while (mBlockedActivityLogs.size() >= LOG_SIZE) {
1191 mBlockedActivityLogs.remove();
1192 }
1193 StringBuffer sb = new StringBuffer()
1194 .append(CarLog.TAG_PACKAGE).append(':')
1195 .append(DateFormat.format(
1196 "MM-dd HH:mm:ss", System.currentTimeMillis())).append(": ")
1197 .append(log);
1198 mBlockedActivityLogs.add(sb.toString());
1199 }
1200
1201 /**
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001202 * Reading policy and setting policy can take time. Run it in a separate handler thread.
1203 */
Keun young Parkb241d022020-04-20 20:31:34 -07001204 private static final class PackageHandler extends Handler {
1205 private static final String TAG = PackageHandler.class.getSimpleName();
1206
Keun young Park6c4fd342019-12-13 12:46:04 -08001207 private static final int MSG_INIT = 0;
1208 private static final int MSG_PARSE_PKG = 1;
1209 private static final int MSG_UPDATE_POLICY = 2;
1210 private static final int MSG_RELEASE = 3;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001211
Keun young Parkb241d022020-04-20 20:31:34 -07001212 private final WeakReference<CarPackageManagerService> mService;
1213
1214 private PackageHandler(Looper looper, CarPackageManagerService service) {
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001215 super(looper);
Keun young Parkb241d022020-04-20 20:31:34 -07001216 mService = new WeakReference<CarPackageManagerService>(service);
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001217 }
1218
1219 private void requestInit() {
1220 Message msg = obtainMessage(MSG_INIT);
1221 sendMessage(msg);
1222 }
1223
1224 private void requestRelease() {
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001225 removeMessages(MSG_UPDATE_POLICY);
Keun-young Park6dcc50b2016-10-10 19:01:11 -07001226 Message msg = obtainMessage(MSG_RELEASE);
1227 sendMessage(msg);
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001228 }
1229
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001230 private void requestUpdatingPolicy(String packageName, CarAppBlockingPolicy policy,
1231 int flags) {
1232 Pair<String, CarAppBlockingPolicy> pair = new Pair<>(packageName, policy);
1233 Message msg = obtainMessage(MSG_UPDATE_POLICY, flags, 0, pair);
1234 sendMessage(msg);
1235 }
1236
Ram Periathiruvadi295954d2018-04-10 18:27:28 -07001237 private void requestParsingInstalledPkgs(long delayMs) {
Yao, Yuxing0c6fc732019-05-10 14:58:49 -07001238 // Parse packages for current user.
1239 removeMessages(MSG_PARSE_PKG);
1240
Ram Periathiruvadi38388302018-02-22 16:42:49 -08001241 Message msg = obtainMessage(MSG_PARSE_PKG);
Ram Periathiruvadi295954d2018-04-10 18:27:28 -07001242 if (delayMs == 0) {
1243 sendMessage(msg);
1244 } else {
1245 sendMessageDelayed(msg, delayMs);
1246 }
Ram Periathiruvadi38388302018-02-22 16:42:49 -08001247 }
1248
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001249 @Override
1250 public void handleMessage(Message msg) {
Keun young Parkb241d022020-04-20 20:31:34 -07001251 CarPackageManagerService service = mService.get();
1252 if (service == null) {
Eric Jeong47b1e242020-12-21 13:41:36 -08001253 Slog.i(TAG, "handleMessage null service");
Keun young Parkb241d022020-04-20 20:31:34 -07001254 return;
1255 }
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001256 switch (msg.what) {
1257 case MSG_INIT:
Keun young Parkb241d022020-04-20 20:31:34 -07001258 service.doHandleInit();
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001259 break;
Ram Periathiruvadi38388302018-02-22 16:42:49 -08001260 case MSG_PARSE_PKG:
Keun young Parkb241d022020-04-20 20:31:34 -07001261 service.doParseInstalledPackages();
Ram Periathiruvadi38388302018-02-22 16:42:49 -08001262 break;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001263 case MSG_UPDATE_POLICY:
1264 Pair<String, CarAppBlockingPolicy> pair =
1265 (Pair<String, CarAppBlockingPolicy>) msg.obj;
Keun young Parkb241d022020-04-20 20:31:34 -07001266 service.doUpdatePolicy(pair.first, pair.second, msg.arg1);
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001267 break;
Keun-young Park6dcc50b2016-10-10 19:01:11 -07001268 case MSG_RELEASE:
Keun young Parkb241d022020-04-20 20:31:34 -07001269 service.doHandleRelease();
Keun-young Park6dcc50b2016-10-10 19:01:11 -07001270 break;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001271 }
1272 }
1273 }
1274
1275 private static class AppBlockingPackageInfoWrapper {
1276 private final AppBlockingPackageInfo info;
1277 /**
1278 * Whether the current info is matching with the target package in system. Mismatch can
1279 * happen for version out of range or signature mismatch.
1280 */
1281 private boolean isMatching;
1282
1283 private AppBlockingPackageInfoWrapper(AppBlockingPackageInfo info, boolean isMatching) {
Ram Periathiruvadie6e2ac32018-05-02 14:57:46 -07001284 this.info = info;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001285 this.isMatching = isMatching;
1286 }
1287
1288 @Override
1289 public String toString() {
1290 return "AppBlockingPackageInfoWrapper [info=" + info + ", isMatching=" + isMatching +
1291 "]";
1292 }
1293 }
1294
1295 /**
1296 * Client policy holder per each client. Should be accessed with CarpackageManagerService.this
1297 * held.
1298 */
1299 private static class ClientPolicy {
Jordan Jozwiak794abcb2020-07-27 08:08:11 -07001300 private final HashMap<String, AppBlockingPackageInfoWrapper> mAllowlistsMap =
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001301 new HashMap<>();
Jordan Jozwiak794abcb2020-07-27 08:08:11 -07001302 private final HashMap<String, AppBlockingPackageInfoWrapper> mBlocklistsMap =
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001303 new HashMap<>();
1304
Jordan Jozwiak794abcb2020-07-27 08:08:11 -07001305 private void replaceAllowlists(AppBlockingPackageInfoWrapper[] allowlists) {
1306 mAllowlistsMap.clear();
1307 addToAllowlists(allowlists);
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001308 }
1309
Jordan Jozwiak794abcb2020-07-27 08:08:11 -07001310 private void addToAllowlists(AppBlockingPackageInfoWrapper[] allowlists) {
1311 if (allowlists == null) {
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001312 return;
1313 }
Jordan Jozwiak794abcb2020-07-27 08:08:11 -07001314 for (AppBlockingPackageInfoWrapper wrapper : allowlists) {
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001315 if (wrapper != null) {
Jordan Jozwiak794abcb2020-07-27 08:08:11 -07001316 mAllowlistsMap.put(wrapper.info.packageName, wrapper);
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001317 }
1318 }
1319 }
1320
Jordan Jozwiak794abcb2020-07-27 08:08:11 -07001321 private void removeAllowlists(AppBlockingPackageInfoWrapper[] allowlists) {
1322 if (allowlists == null) {
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001323 return;
1324 }
Jordan Jozwiak794abcb2020-07-27 08:08:11 -07001325 for (AppBlockingPackageInfoWrapper wrapper : allowlists) {
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001326 if (wrapper != null) {
Jordan Jozwiak794abcb2020-07-27 08:08:11 -07001327 mAllowlistsMap.remove(wrapper.info.packageName);
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001328 }
1329 }
1330 }
1331
Jordan Jozwiak794abcb2020-07-27 08:08:11 -07001332 private void replaceBlocklists(AppBlockingPackageInfoWrapper[] blocklists) {
1333 mBlocklistsMap.clear();
1334 addToBlocklists(blocklists);
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001335 }
1336
Jordan Jozwiak794abcb2020-07-27 08:08:11 -07001337 private void addToBlocklists(AppBlockingPackageInfoWrapper[] blocklists) {
1338 if (blocklists == null) {
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001339 return;
1340 }
Jordan Jozwiak794abcb2020-07-27 08:08:11 -07001341 for (AppBlockingPackageInfoWrapper wrapper : blocklists) {
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001342 if (wrapper != null) {
Jordan Jozwiak794abcb2020-07-27 08:08:11 -07001343 mBlocklistsMap.put(wrapper.info.packageName, wrapper);
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001344 }
1345 }
1346 }
1347
Jordan Jozwiak794abcb2020-07-27 08:08:11 -07001348 private void removeBlocklists(AppBlockingPackageInfoWrapper[] blocklists) {
1349 if (blocklists == null) {
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001350 return;
1351 }
Jordan Jozwiak794abcb2020-07-27 08:08:11 -07001352 for (AppBlockingPackageInfoWrapper wrapper : blocklists) {
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001353 if (wrapper != null) {
Jordan Jozwiak794abcb2020-07-27 08:08:11 -07001354 mBlocklistsMap.remove(wrapper.info.packageName);
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001355 }
1356 }
1357 }
1358 }
Keun-young Park4727da32016-05-31 10:00:51 -07001359
1360 private class ActivityLaunchListener
Ram Periathiruvadie6e2ac32018-05-02 14:57:46 -07001361 implements SystemActivityMonitoringService.ActivityLaunchListener {
Keun-young Park4727da32016-05-31 10:00:51 -07001362 @Override
1363 public void onActivityLaunch(TopTaskInfoContainer topTask) {
Yao, Yuxing2646cff2019-04-23 17:01:26 -07001364 if (topTask == null) {
Eric Jeong47b1e242020-12-21 13:41:36 -08001365 Slog.e(CarLog.TAG_PACKAGE, "Received callback with null top task.");
Yao, Yuxing2646cff2019-04-23 17:01:26 -07001366 return;
1367 }
Keun-young Park4727da32016-05-31 10:00:51 -07001368 blockTopActivityIfNecessary(topTask);
1369 }
1370 }
1371
Ram Periathiruvadi2da6d0e2018-01-26 18:02:10 -08001372 /**
1373 * Listens to the UX restrictions from {@link CarUxRestrictionsManagerService} and initiates
1374 * checking if the foreground Activity should be blocked.
1375 */
1376 private class UxRestrictionsListener extends ICarUxRestrictionsChangeListener.Stub {
Yan Zhu211b1fe2019-11-06 15:54:19 -08001377 @GuardedBy("mLock")
Ram Periathiruvadi2da6d0e2018-01-26 18:02:10 -08001378 @Nullable
1379 private CarUxRestrictions mCurrentUxRestrictions;
1380 private final CarUxRestrictionsManagerService uxRestrictionsService;
Keun-young Park4727da32016-05-31 10:00:51 -07001381
Ram Periathiruvadi2da6d0e2018-01-26 18:02:10 -08001382 public UxRestrictionsListener(CarUxRestrictionsManagerService service) {
1383 uxRestrictionsService = service;
Ram Periathiruvadi2da6d0e2018-01-26 18:02:10 -08001384 }
1385
1386 @Override
1387 public void onUxRestrictionsChanged(CarUxRestrictions restrictions) {
Yao, Yuxing4ddb2c62019-02-04 11:26:46 -08001388 if (DBG_POLICY_ENFORCEMENT) {
Eric Jeong47b1e242020-12-21 13:41:36 -08001389 Slog.d(CarLog.TAG_PACKAGE, "Received uxr restrictions: "
Ram Periathiruvadi2da6d0e2018-01-26 18:02:10 -08001390 + restrictions.isRequiresDistractionOptimization()
1391 + " : " + restrictions.getActiveRestrictions());
1392 }
Ram Periathiruvadic57678d2018-04-23 09:18:33 -07001393 // We are not handling the restrictions until we know what is allowed and what is not.
1394 // This is to handle some situations, where car service is ready and getting sensor
1395 // data but we haven't received the boot complete intents.
1396 if (!mHasParsedPackages) {
1397 return;
1398 }
1399
Yan Zhu211b1fe2019-11-06 15:54:19 -08001400 synchronized (mLock) {
Ram Periathiruvadi2da6d0e2018-01-26 18:02:10 -08001401 mCurrentUxRestrictions = new CarUxRestrictions(restrictions);
1402 }
1403 checkIfTopActivityNeedsBlocking();
1404 }
1405
1406 private void checkIfTopActivityNeedsBlocking() {
1407 boolean shouldCheck = false;
Yan Zhu211b1fe2019-11-06 15:54:19 -08001408 synchronized (mLock) {
Ram Periathiruvadi2da6d0e2018-01-26 18:02:10 -08001409 if (mCurrentUxRestrictions != null
1410 && mCurrentUxRestrictions.isRequiresDistractionOptimization()) {
1411 shouldCheck = true;
Keun-young Park4727da32016-05-31 10:00:51 -07001412 }
1413 }
Yao, Yuxing4ddb2c62019-02-04 11:26:46 -08001414 if (DBG_POLICY_ENFORCEMENT) {
Eric Jeong47b1e242020-12-21 13:41:36 -08001415 Slog.d(CarLog.TAG_PACKAGE, "Should check top tasks?: " + shouldCheck);
Ram Periathiruvadi2da6d0e2018-01-26 18:02:10 -08001416 }
1417 if (shouldCheck) {
Yao, Yuxingd525de12019-05-06 15:11:48 -07001418 // Loop over all top tasks to ensure tasks on virtual display can also be blocked.
Keun-young Park4727da32016-05-31 10:00:51 -07001419 blockTopActivitiesIfNecessary();
1420 }
1421 }
1422
Yan Zhu211b1fe2019-11-06 15:54:19 -08001423 private boolean isRestricted() {
Ram Periathiruvadi2da6d0e2018-01-26 18:02:10 -08001424 // if current restrictions is null, try querying the service, once.
Yan Zhu211b1fe2019-11-06 15:54:19 -08001425 synchronized (mLock) {
1426 if (mCurrentUxRestrictions == null) {
1427 mCurrentUxRestrictions = uxRestrictionsService.getCurrentUxRestrictions();
1428 }
1429 if (mCurrentUxRestrictions != null) {
1430 return mCurrentUxRestrictions.isRequiresDistractionOptimization();
1431 }
Ram Periathiruvadi2da6d0e2018-01-26 18:02:10 -08001432 }
Yan Zhu211b1fe2019-11-06 15:54:19 -08001433
Ram Periathiruvadi2da6d0e2018-01-26 18:02:10 -08001434 // If restriction information is still not available (could happen during bootup),
1435 // return not restricted. This maintains parity with previous implementation but needs
1436 // a revisit as we test more.
1437 return false;
Keun-young Park4727da32016-05-31 10:00:51 -07001438 }
1439 }
Ram Periathiruvadi38388302018-02-22 16:42:49 -08001440
1441 /**
Ram Periathiruvadie6e2ac32018-05-02 14:57:46 -07001442 * Listens to the package install/uninstall events to know when to initiate parsing
1443 * installed packages.
1444 */
1445 private class PackageParsingEventReceiver extends BroadcastReceiver {
1446 private static final long PACKAGE_PARSING_DELAY_MS = 500;
1447
1448 @Override
1449 public void onReceive(Context context, Intent intent) {
1450 if (intent == null || intent.getAction() == null) {
1451 return;
1452 }
1453 if (DBG_POLICY_CHECK) {
Eric Jeong47b1e242020-12-21 13:41:36 -08001454 Slog.d(CarLog.TAG_PACKAGE,
Ram Periathiruvadie6e2ac32018-05-02 14:57:46 -07001455 "PackageParsingEventReceiver Received " + intent.getAction());
1456 }
1457 String action = intent.getAction();
1458 if (isPackageManagerAction(action)) {
Ram Periathiruvadi295954d2018-04-10 18:27:28 -07001459 // send a delayed message so if we received multiple related intents, we parse
1460 // only once.
1461 logEventChange(intent);
1462 mHandler.requestParsingInstalledPkgs(PACKAGE_PARSING_DELAY_MS);
1463 }
1464 }
1465
1466 private boolean isPackageManagerAction(String action) {
Jordan Jozwiak12d59e02019-06-20 18:10:21 -07001467 return mPackageManagerActions.contains(action);
Ram Periathiruvadi295954d2018-04-10 18:27:28 -07001468 }
1469
1470 /**
1471 * Convenience log function to log what changed. Logs only when more debug logs
1472 * are needed - DBG_POLICY_CHECK needs to be true
1473 */
1474 private void logEventChange(Intent intent) {
1475 if (!DBG_POLICY_CHECK || intent == null) {
1476 return;
1477 }
1478
1479 String packageName = intent.getData().getSchemeSpecificPart();
Eric Jeong47b1e242020-12-21 13:41:36 -08001480 Slog.d(CarLog.TAG_PACKAGE, "Pkg Changed:" + packageName);
Ram Periathiruvadi295954d2018-04-10 18:27:28 -07001481 String action = intent.getAction();
1482 if (action == null) {
1483 return;
1484 }
1485 if (action.equals(Intent.ACTION_PACKAGE_CHANGED)) {
Eric Jeong47b1e242020-12-21 13:41:36 -08001486 Slog.d(CarLog.TAG_PACKAGE, "Changed components");
Ram Periathiruvadi295954d2018-04-10 18:27:28 -07001487 String[] cc = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST);
1488 if (cc != null) {
1489 for (String c : cc) {
Eric Jeong47b1e242020-12-21 13:41:36 -08001490 Slog.d(CarLog.TAG_PACKAGE, c);
Ram Periathiruvadi295954d2018-04-10 18:27:28 -07001491 }
1492 }
1493 } else if (action.equals(Intent.ACTION_PACKAGE_REMOVED)
1494 || action.equals(Intent.ACTION_PACKAGE_ADDED)) {
Eric Jeong47b1e242020-12-21 13:41:36 -08001495 Slog.d(CarLog.TAG_PACKAGE, action + " Replacing?: " + intent.getBooleanExtra(
Ram Periathiruvadi295954d2018-04-10 18:27:28 -07001496 Intent.EXTRA_REPLACING, false));
Ram Periathiruvadi38388302018-02-22 16:42:49 -08001497 }
1498 }
1499 }
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001500}