blob: 781b9ef50a6d0f1cfa06491dfdc922109c8086f5 [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
Ram Periathiruvadi2da6d0e2018-01-26 18:02:10 -080019import android.annotation.Nullable;
Keun-young Park4727da32016-05-31 10:00:51 -070020import android.app.ActivityManager.StackInfo;
Keun-young Parke54ac272016-02-16 19:02:18 -080021import android.car.Car;
22import android.car.content.pm.AppBlockingPackageInfo;
23import android.car.content.pm.CarAppBlockingPolicy;
24import android.car.content.pm.CarAppBlockingPolicyService;
25import android.car.content.pm.CarPackageManager;
26import android.car.content.pm.ICarPackageManager;
Ram Periathiruvadi2da6d0e2018-01-26 18:02:10 -080027import android.car.drivingstate.CarUxRestrictions;
28import android.car.drivingstate.ICarUxRestrictionsChangeListener;
Ram Periathiruvadi38388302018-02-22 16:42:49 -080029import android.content.BroadcastReceiver;
Keun-young Park4727da32016-05-31 10:00:51 -070030import android.content.ComponentName;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -080031import android.content.Context;
32import android.content.Intent;
Ram Periathiruvadi38388302018-02-22 16:42:49 -080033import android.content.IntentFilter;
34import android.content.pm.ActivityInfo;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -080035import android.content.pm.PackageInfo;
36import android.content.pm.PackageManager;
37import android.content.pm.PackageManager.NameNotFoundException;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -080038import android.content.pm.ResolveInfo;
Pavel Maltsev0d07c762016-11-03 16:40:15 -070039import android.content.pm.ServiceInfo;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -080040import android.content.pm.Signature;
Keun-young Park4727da32016-05-31 10:00:51 -070041import android.content.res.Resources;
Ram Periathiruvadia6e0d9b2018-04-25 20:19:22 -070042import android.os.Binder;
Ram Periathiruvadid937c322018-06-13 12:28:12 -070043import android.os.Build;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -080044import android.os.Handler;
45import android.os.HandlerThread;
46import android.os.Looper;
47import android.os.Message;
Ram Periathiruvadia6e0d9b2018-04-25 20:19:22 -070048import android.os.Process;
Ram Periathiruvadi402d12e2018-07-11 18:31:13 -070049import android.text.TextUtils;
Yao, Yuxingd1d6a372018-05-08 10:37:43 -070050import android.text.format.DateFormat;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -080051import android.util.ArraySet;
52import android.util.Log;
53import android.util.Pair;
Yao, Yuxingcfcc59f2019-03-05 16:35:47 -080054import android.view.Display;
Ram Periathiruvadi8ef1a202018-03-16 17:49:21 -070055
Keun-young Park4aeb4bf2015-12-08 18:31:33 -080056import com.android.car.CarLog;
57import com.android.car.CarServiceBase;
58import com.android.car.CarServiceUtils;
Ram Periathiruvadi2da6d0e2018-01-26 18:02:10 -080059import com.android.car.CarUxRestrictionsManagerService;
Keun-young Park4727da32016-05-31 10:00:51 -070060import com.android.car.R;
61import com.android.car.SystemActivityMonitoringService;
62import com.android.car.SystemActivityMonitoringService.TopTaskInfoContainer;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -080063import com.android.internal.annotations.GuardedBy;
Ram Periathiruvadi8ef1a202018-03-16 17:49:21 -070064import com.android.internal.annotations.VisibleForTesting;
Ram Periathiruvadi38388302018-02-22 16:42:49 -080065
Keun-young Park4aeb4bf2015-12-08 18:31:33 -080066import java.io.PrintWriter;
Ram Periathiruvadi38388302018-02-22 16:42:49 -080067import java.util.ArrayList;
Ram Periathiruvadi295954d2018-04-10 18:27:28 -070068import java.util.Arrays;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -080069import java.util.HashMap;
70import java.util.LinkedList;
71import java.util.List;
Ram Periathiruvadi46a3a3d2018-03-23 16:58:32 -070072import java.util.Map;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -080073import java.util.Map.Entry;
Keun-young Park4727da32016-05-31 10:00:51 -070074import java.util.Set;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -080075
Keun-young Park4aeb4bf2015-12-08 18:31:33 -080076public class CarPackageManagerService extends ICarPackageManager.Stub implements CarServiceBase {
Ram Periathiruvadi2da6d0e2018-01-26 18:02:10 -080077 private static final boolean DBG_POLICY_SET = false;
78 private static final boolean DBG_POLICY_CHECK = false;
79 private static final boolean DBG_POLICY_ENFORCEMENT = false;
Ram Periathiruvadi46a3a3d2018-03-23 16:58:32 -070080 // Delimiters to parse packages and activities in the configuration XML resource.
81 private static final String PACKAGE_DELIMITER = ",";
82 private static final String PACKAGE_ACTIVITY_DELIMITER = "/";
Yao, Yuxingd1d6a372018-05-08 10:37:43 -070083 private static final int LOG_SIZE = 20;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -080084
85 private final Context mContext;
Keun-young Park4727da32016-05-31 10:00:51 -070086 private final SystemActivityMonitoringService mSystemActivityMonitoringService;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -080087 private final PackageManager mPackageManager;
88
89 private final HandlerThread mHandlerThread;
90 private final PackageHandler mHandler;
91
Yao, Yuxingd1d6a372018-05-08 10:37:43 -070092 // For dumpsys logging.
93 private final LinkedList<String> mBlockedActivityLogs = new LinkedList<>();
94
Ram Periathiruvadi46a3a3d2018-03-23 16:58:32 -070095 // Store the white list and black list strings from the resource file.
96 private String mConfiguredWhitelist;
97 private String mConfiguredBlacklist;
Ram Periathiruvadid937c322018-06-13 12:28:12 -070098 private final List<String> mAllowedAppInstallSources;
99
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800100 /**
101 * Hold policy set from policy service or client.
102 * Key: packageName of policy service
103 */
104 @GuardedBy("this")
Ram Periathiruvadi2da6d0e2018-01-26 18:02:10 -0800105 private final HashMap<String, ClientPolicy> mClientPolicies = new HashMap<>();
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800106 @GuardedBy("this")
Ram Periathiruvadi46a3a3d2018-03-23 16:58:32 -0700107 private HashMap<String, AppBlockingPackageInfoWrapper> mActivityWhitelistMap = new HashMap<>();
108 // The list corresponding to the one configured in <activityBlacklist>
109 @GuardedBy("this")
110 private HashMap<String, AppBlockingPackageInfoWrapper> mActivityBlacklistMap = new HashMap<>();
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800111 @GuardedBy("this")
112 private LinkedList<AppBlockingPolicyProxy> mProxies;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800113
114 @GuardedBy("this")
115 private final LinkedList<CarAppBlockingPolicy> mWaitingPolicies = new LinkedList<>();
116
Ram Periathiruvadi2da6d0e2018-01-26 18:02:10 -0800117 private final CarUxRestrictionsManagerService mCarUxRestrictionsService;
Ram Periathiruvadibf0eab72018-02-06 12:32:43 -0800118 private boolean mEnableActivityBlocking;
Keun-young Park4727da32016-05-31 10:00:51 -0700119 private final ComponentName mActivityBlockingActivity;
120
121 private final ActivityLaunchListener mActivityLaunchListener = new ActivityLaunchListener();
Ram Periathiruvadi2da6d0e2018-01-26 18:02:10 -0800122 private final UxRestrictionsListener mUxRestrictionsListener;
Ram Periathiruvadi295954d2018-04-10 18:27:28 -0700123
124 // Information related to when the installed packages should be parsed for building a white and
125 // black list
126 private final List<String> mPackageManagerActions = Arrays.asList(
127 Intent.ACTION_PACKAGE_ADDED,
128 Intent.ACTION_PACKAGE_CHANGED,
129 Intent.ACTION_PACKAGE_DATA_CLEARED,
130 Intent.ACTION_PACKAGE_REMOVED,
131 Intent.ACTION_PACKAGE_REPLACED,
132 Intent.ACTION_PACKAGE_FULLY_REMOVED);
133
134 private final PackageParsingEventReceiver mPackageParsingEventReceiver =
135 new PackageParsingEventReceiver();
Ram Periathiruvadie6e2ac32018-05-02 14:57:46 -0700136 private final BootEventReceiver mBootEventReceiver = new BootEventReceiver();
Keun-young Park4727da32016-05-31 10:00:51 -0700137
Ram Periathiruvadic57678d2018-04-23 09:18:33 -0700138 // To track if the packages have been parsed for building white/black lists. If we haven't had
139 // received any intents (boot complete or package changed), then the white list is null leading
140 // to blocking everything. So, no blocking until we have had a chance to parse the packages.
141 private boolean mHasParsedPackages;
Ram Periathiruvadie6e2ac32018-05-02 14:57:46 -0700142 // To track if we received the boot complete intent.
143 private boolean mBootLockedIntentRx;
Ram Periathiruvadic57678d2018-04-23 09:18:33 -0700144
Yao, Yuxing14e83b42018-10-29 18:29:56 -0700145 /**
146 * Name of blocked activity.
147 *
148 * @hide
149 */
150 public static final String BLOCKING_INTENT_EXTRA_BLOCKED_ACTIVITY_NAME = "blocked_activity";
151 /**
152 * int task id of the blocked task.
153 *
154 * @hide
155 */
156 public static final String BLOCKING_INTENT_EXTRA_BLOCKED_TASK_ID = "blocked_task_id";
157 /**
158 * Name of root activity of blocked task.
159 *
160 * @hide
161 */
162 public static final String BLOCKING_INTENT_EXTRA_ROOT_ACTIVITY_NAME = "root_activity_name";
163 /**
164 * Boolean indicating whether the root activity is distraction-optimized (DO).
165 * Blocking screen should show a button to restart the task if {@code true}.
166 *
167 * @hide
168 */
169 public static final String BLOCKING_INTENT_EXTRA_IS_ROOT_ACTIVITY_DO = "is_root_activity_do";
170
Ram Periathiruvadi2da6d0e2018-01-26 18:02:10 -0800171 public CarPackageManagerService(Context context,
172 CarUxRestrictionsManagerService uxRestrictionsService,
Keun-young Park4727da32016-05-31 10:00:51 -0700173 SystemActivityMonitoringService systemActivityMonitoringService) {
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800174 mContext = context;
Ram Periathiruvadi2da6d0e2018-01-26 18:02:10 -0800175 mCarUxRestrictionsService = uxRestrictionsService;
Keun-young Park4727da32016-05-31 10:00:51 -0700176 mSystemActivityMonitoringService = systemActivityMonitoringService;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800177 mPackageManager = mContext.getPackageManager();
Ram Periathiruvadi2da6d0e2018-01-26 18:02:10 -0800178 mUxRestrictionsListener = new UxRestrictionsListener(uxRestrictionsService);
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800179 mHandlerThread = new HandlerThread(CarLog.TAG_PACKAGE);
180 mHandlerThread.start();
181 mHandler = new PackageHandler(mHandlerThread.getLooper());
Keun-young Park4727da32016-05-31 10:00:51 -0700182 Resources res = context.getResources();
183 mEnableActivityBlocking = res.getBoolean(R.bool.enableActivityBlockingForSafety);
184 String blockingActivity = res.getString(R.string.activityBlockingActivity);
185 mActivityBlockingActivity = ComponentName.unflattenFromString(blockingActivity);
Ram Periathiruvadid937c322018-06-13 12:28:12 -0700186 mAllowedAppInstallSources = Arrays.asList(
187 res.getStringArray(R.array.allowedAppInstallSources));
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800188 }
189
Ram Periathiruvadid937c322018-06-13 12:28:12 -0700190
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800191 @Override
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800192 public void setAppBlockingPolicy(String packageName, CarAppBlockingPolicy policy, int flags) {
193 if (DBG_POLICY_SET) {
194 Log.i(CarLog.TAG_PACKAGE, "policy setting from binder call, client:" + packageName);
195 }
196 doSetAppBlockingPolicy(packageName, policy, flags, true /*setNow*/);
197 }
198
Yao, Yuxingd1d6a372018-05-08 10:37:43 -0700199 /**
200 * Restarts the requested task. If task with {@code taskId} does not exist, do nothing.
201 */
202 @Override
203 public void restartTask(int taskId) {
204 mSystemActivityMonitoringService.restartTask(taskId);
205 }
206
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800207 private void doSetAppBlockingPolicy(String packageName, CarAppBlockingPolicy policy, int flags,
208 boolean setNow) {
209 if (mContext.checkCallingOrSelfPermission(Car.PERMISSION_CONTROL_APP_BLOCKING)
210 != PackageManager.PERMISSION_GRANTED) {
211 throw new SecurityException(
212 "requires permission " + Car.PERMISSION_CONTROL_APP_BLOCKING);
213 }
Enrico Granata3da3c612017-01-20 15:24:30 -0800214 CarServiceUtils.assertPackageName(mContext, packageName);
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800215 if (policy == null) {
216 throw new IllegalArgumentException("policy cannot be null");
217 }
218 if ((flags & CarPackageManager.FLAG_SET_POLICY_ADD) != 0 &&
219 (flags & CarPackageManager.FLAG_SET_POLICY_REMOVE) != 0) {
220 throw new IllegalArgumentException(
221 "Cannot set both FLAG_SET_POLICY_ADD and FLAG_SET_POLICY_REMOVE flag");
222 }
223 mHandler.requestUpdatingPolicy(packageName, policy, flags);
224 if (setNow) {
225 mHandler.requestPolicySetting();
226 if ((flags & CarPackageManager.FLAG_SET_POLICY_WAIT_FOR_CHANGE) != 0) {
227 synchronized (policy) {
228 try {
229 policy.wait();
230 } catch (InterruptedException e) {
231 }
232 }
233 }
234 }
235 }
236
237 @Override
Ram Periathiruvadie154f582018-03-21 21:53:27 -0700238 public boolean isActivityDistractionOptimized(String packageName, String className) {
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800239 assertPackageAndClassName(packageName, className);
240 synchronized (this) {
241 if (DBG_POLICY_CHECK) {
Ram Periathiruvadie154f582018-03-21 21:53:27 -0700242 Log.i(CarLog.TAG_PACKAGE, "isActivityDistractionOptimized"
243 + dumpPoliciesLocked(false));
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800244 }
245 AppBlockingPackageInfo info = searchFromBlacklistsLocked(packageName);
246 if (info != null) {
247 return false;
248 }
249 return isActivityInWhitelistsLocked(packageName, className);
250 }
251 }
252
253 @Override
Ram Periathiruvadie154f582018-03-21 21:53:27 -0700254 public boolean isServiceDistractionOptimized(String packageName, String className) {
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800255 if (packageName == null) {
256 throw new IllegalArgumentException("Package name null");
257 }
258 synchronized (this) {
259 if (DBG_POLICY_CHECK) {
Ram Periathiruvadie154f582018-03-21 21:53:27 -0700260 Log.i(CarLog.TAG_PACKAGE, "isServiceDistractionOptimized"
261 + dumpPoliciesLocked(false));
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800262 }
263 AppBlockingPackageInfo info = searchFromBlacklistsLocked(packageName);
264 if (info != null) {
265 return false;
266 }
267 info = searchFromWhitelistsLocked(packageName);
268 if (info != null) {
269 return true;
270 }
271 }
272 return false;
273 }
274
Keun-young Park4727da32016-05-31 10:00:51 -0700275 @Override
276 public boolean isActivityBackedBySafeActivity(ComponentName activityName) {
Ram Periathiruvadibf0eab72018-02-06 12:32:43 -0800277 if (!mUxRestrictionsListener.isRestricted()) {
Keun-young Park4727da32016-05-31 10:00:51 -0700278 return true;
279 }
280 StackInfo info = mSystemActivityMonitoringService.getFocusedStackForTopActivity(
281 activityName);
282 if (info == null) { // not top in focused stack
283 return true;
284 }
285 if (info.taskNames.length <= 1) { // nothing below this.
286 return false;
287 }
288 ComponentName activityBehind = ComponentName.unflattenFromString(
289 info.taskNames[info.taskNames.length - 2]);
Ram Periathiruvadie154f582018-03-21 21:53:27 -0700290 return isActivityDistractionOptimized(activityBehind.getPackageName(),
Keun-young Park4727da32016-05-31 10:00:51 -0700291 activityBehind.getClassName());
292 }
293
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800294 public Looper getLooper() {
295 return mHandlerThread.getLooper();
296 }
297
298 private void assertPackageAndClassName(String packageName, String className) {
299 if (packageName == null) {
300 throw new IllegalArgumentException("Package name null");
301 }
302 if (className == null) {
303 throw new IllegalArgumentException("Class name null");
304 }
305 }
306
Andreas Gampe985ca2f2018-02-09 12:57:54 -0800307 @GuardedBy("this")
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800308 private AppBlockingPackageInfo searchFromBlacklistsLocked(String packageName) {
309 for (ClientPolicy policy : mClientPolicies.values()) {
310 AppBlockingPackageInfoWrapper wrapper = policy.blacklistsMap.get(packageName);
311 if (wrapper != null && wrapper.isMatching) {
312 return wrapper.info;
313 }
314 }
Ram Periathiruvadi46a3a3d2018-03-23 16:58:32 -0700315 AppBlockingPackageInfoWrapper wrapper = mActivityBlacklistMap.get(packageName);
316 return (wrapper != null) ? wrapper.info : null;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800317 }
318
Andreas Gampe985ca2f2018-02-09 12:57:54 -0800319 @GuardedBy("this")
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800320 private AppBlockingPackageInfo searchFromWhitelistsLocked(String packageName) {
321 for (ClientPolicy policy : mClientPolicies.values()) {
322 AppBlockingPackageInfoWrapper wrapper = policy.whitelistsMap.get(packageName);
323 if (wrapper != null && wrapper.isMatching) {
324 return wrapper.info;
325 }
326 }
Ram Periathiruvadi46a3a3d2018-03-23 16:58:32 -0700327 AppBlockingPackageInfoWrapper wrapper = mActivityWhitelistMap.get(packageName);
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800328 return (wrapper != null) ? wrapper.info : null;
329 }
330
Andreas Gampe985ca2f2018-02-09 12:57:54 -0800331 @GuardedBy("this")
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800332 private boolean isActivityInWhitelistsLocked(String packageName, String className) {
333 for (ClientPolicy policy : mClientPolicies.values()) {
334 if (isActivityInMapAndMatching(policy.whitelistsMap, packageName, className)) {
335 return true;
336 }
337 }
Ram Periathiruvadi46a3a3d2018-03-23 16:58:32 -0700338 return isActivityInMapAndMatching(mActivityWhitelistMap, packageName, className);
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800339 }
340
341 private boolean isActivityInMapAndMatching(HashMap<String, AppBlockingPackageInfoWrapper> map,
342 String packageName, String className) {
343 AppBlockingPackageInfoWrapper wrapper = map.get(packageName);
344 if (wrapper == null || !wrapper.isMatching) {
Ram Periathiruvadi38388302018-02-22 16:42:49 -0800345 if (DBG_POLICY_CHECK) {
346 Log.d(CarLog.TAG_PACKAGE, "Pkg not in whitelist:" + packageName);
347 }
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800348 return false;
349 }
350 return wrapper.info.isActivityCovered(className);
351 }
352
353 @Override
354 public void init() {
Keun-young Park98960812016-10-04 12:50:54 -0700355 synchronized (this) {
356 mHandler.requestInit();
Keun-young Park4727da32016-05-31 10:00:51 -0700357 }
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800358 }
359
360 @Override
361 public void release() {
362 synchronized (this) {
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800363 mHandler.requestRelease();
Keun-young Park6dcc50b2016-10-10 19:01:11 -0700364 // wait for release do be done. This guarantees that init is done.
365 try {
366 wait();
367 } catch (InterruptedException e) {
368 }
Ram Periathiruvadic57678d2018-04-23 09:18:33 -0700369 mHasParsedPackages = false;
Ram Periathiruvadi46a3a3d2018-03-23 16:58:32 -0700370 mActivityWhitelistMap.clear();
371 mActivityBlacklistMap.clear();
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800372 mClientPolicies.clear();
373 if (mProxies != null) {
374 for (AppBlockingPolicyProxy proxy : mProxies) {
375 proxy.disconnect();
376 }
377 mProxies.clear();
378 }
379 wakeupClientsWaitingForPolicySetitngLocked();
380 }
Ram Periathiruvadi295954d2018-04-10 18:27:28 -0700381 mContext.unregisterReceiver(mPackageParsingEventReceiver);
Ram Periathiruvadie6e2ac32018-05-02 14:57:46 -0700382 mContext.unregisterReceiver(mBootEventReceiver);
Ram Periathiruvadi2da6d0e2018-01-26 18:02:10 -0800383 mCarUxRestrictionsService.unregisterUxRestrictionsChangeListener(mUxRestrictionsListener);
Keun-young Park98960812016-10-04 12:50:54 -0700384 mSystemActivityMonitoringService.registerActivityLaunchListener(null);
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800385 }
386
387 // run from HandlerThread
388 private void doHandleInit() {
Ram Periathiruvadi295954d2018-04-10 18:27:28 -0700389 startAppBlockingPolicies();
Ram Periathiruvadie6e2ac32018-05-02 14:57:46 -0700390 IntentFilter bootIntent = new IntentFilter();
391 bootIntent.addAction(Intent.ACTION_LOCKED_BOOT_COMPLETED);
392 mContext.registerReceiver(mBootEventReceiver, bootIntent);
Ram Periathiruvadi295954d2018-04-10 18:27:28 -0700393 IntentFilter pkgParseIntent = new IntentFilter();
Ram Periathiruvadi295954d2018-04-10 18:27:28 -0700394 for (String action : mPackageManagerActions) {
395 pkgParseIntent.addAction(action);
396 }
397 pkgParseIntent.addDataScheme("package");
398 mContext.registerReceiver(mPackageParsingEventReceiver, pkgParseIntent);
Keun-young Park6dcc50b2016-10-10 19:01:11 -0700399 try {
Ram Periathiruvadi2da6d0e2018-01-26 18:02:10 -0800400 mCarUxRestrictionsService.registerUxRestrictionsChangeListener(mUxRestrictionsListener);
Keun-young Park6dcc50b2016-10-10 19:01:11 -0700401 } catch (IllegalArgumentException e) {
402 // can happen while mocking is going on while init is still done.
403 Log.w(CarLog.TAG_PACKAGE, "sensor subscription failed", e);
404 return;
405 }
Keun-young Park98960812016-10-04 12:50:54 -0700406 mSystemActivityMonitoringService.registerActivityLaunchListener(
407 mActivityLaunchListener);
Ram Periathiruvadi38388302018-02-22 16:42:49 -0800408 }
409
410 private void doParseInstalledPackages() {
Ram Periathiruvadi46a3a3d2018-03-23 16:58:32 -0700411 generateActivityWhitelistMap();
412 generateActivityBlacklistMap();
Ram Periathiruvadic57678d2018-04-23 09:18:33 -0700413 synchronized (this) {
414 mHasParsedPackages = true;
415 }
Ram Periathiruvadi38388302018-02-22 16:42:49 -0800416 mUxRestrictionsListener.checkIfTopActivityNeedsBlocking();
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800417 }
418
Keun-young Park6dcc50b2016-10-10 19:01:11 -0700419 private synchronized void doHandleRelease() {
420 notifyAll();
421 }
422
Andreas Gampe985ca2f2018-02-09 12:57:54 -0800423 @GuardedBy("this")
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800424 private void wakeupClientsWaitingForPolicySetitngLocked() {
425 for (CarAppBlockingPolicy waitingPolicy : mWaitingPolicies) {
426 synchronized (waitingPolicy) {
427 waitingPolicy.notifyAll();
428 }
429 }
430 mWaitingPolicies.clear();
431 }
432
433 private void doSetPolicy() {
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800434 synchronized (this) {
435 wakeupClientsWaitingForPolicySetitngLocked();
436 }
Keun-young Park4727da32016-05-31 10:00:51 -0700437 blockTopActivitiesIfNecessary();
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800438 }
439
440 private void doUpdatePolicy(String packageName, CarAppBlockingPolicy policy, int flags) {
441 if (DBG_POLICY_SET) {
442 Log.i(CarLog.TAG_PACKAGE, "setting policy from:" + packageName + ",policy:" + policy +
443 ",flags:0x" + Integer.toHexString(flags));
444 }
445 AppBlockingPackageInfoWrapper[] blacklistWrapper = verifyList(policy.blacklists);
446 AppBlockingPackageInfoWrapper[] whitelistWrapper = verifyList(policy.whitelists);
447 synchronized (this) {
448 ClientPolicy clientPolicy = mClientPolicies.get(packageName);
449 if (clientPolicy == null) {
450 clientPolicy = new ClientPolicy();
451 mClientPolicies.put(packageName, clientPolicy);
452 }
453 if ((flags & CarPackageManager.FLAG_SET_POLICY_ADD) != 0) {
454 clientPolicy.addToBlacklists(blacklistWrapper);
455 clientPolicy.addToWhitelists(whitelistWrapper);
456 } else if ((flags & CarPackageManager.FLAG_SET_POLICY_REMOVE) != 0) {
457 clientPolicy.removeBlacklists(blacklistWrapper);
458 clientPolicy.removeWhitelists(whitelistWrapper);
459 } else { //replace.
460 clientPolicy.replaceBlacklists(blacklistWrapper);
461 clientPolicy.replaceWhitelists(whitelistWrapper);
462 }
463 if ((flags & CarPackageManager.FLAG_SET_POLICY_WAIT_FOR_CHANGE) != 0) {
464 mWaitingPolicies.add(policy);
465 }
466 if (DBG_POLICY_SET) {
467 Log.i(CarLog.TAG_PACKAGE, "policy set:" + dumpPoliciesLocked(false));
468 }
469 }
Keun-young Park4727da32016-05-31 10:00:51 -0700470 blockTopActivitiesIfNecessary();
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800471 }
472
473 private AppBlockingPackageInfoWrapper[] verifyList(AppBlockingPackageInfo[] list) {
474 if (list == null) {
475 return null;
476 }
477 LinkedList<AppBlockingPackageInfoWrapper> wrappers = new LinkedList<>();
478 for (int i = 0; i < list.length; i++) {
479 AppBlockingPackageInfo info = list[i];
480 if (info == null) {
481 continue;
482 }
483 boolean isMatching = isInstalledPackageMatching(info);
484 wrappers.add(new AppBlockingPackageInfoWrapper(info, isMatching));
485 }
486 return wrappers.toArray(new AppBlockingPackageInfoWrapper[wrappers.size()]);
487 }
488
489 boolean isInstalledPackageMatching(AppBlockingPackageInfo info) {
490 PackageInfo packageInfo = null;
491 try {
492 packageInfo = mPackageManager.getPackageInfo(info.packageName,
493 PackageManager.GET_SIGNATURES);
494 } catch (NameNotFoundException e) {
495 return false;
496 }
497 if (packageInfo == null) {
498 return false;
499 }
500 // if it is system app and client specified the flag, do not check signature
501 if ((info.flags & AppBlockingPackageInfo.FLAG_SYSTEM_APP) == 0 ||
502 (!packageInfo.applicationInfo.isSystemApp() &&
503 !packageInfo.applicationInfo.isUpdatedSystemApp())) {
504 Signature[] signatires = packageInfo.signatures;
505 if (!isAnySignatureMatching(signatires, info.signatures)) {
506 return false;
507 }
508 }
509 int version = packageInfo.versionCode;
510 if (info.minRevisionCode == 0) {
511 if (info.maxRevisionCode == 0) { // all versions
512 return true;
513 } else { // only max version matters
514 return info.maxRevisionCode > version;
515 }
516 } else { // min version matters
517 if (info.maxRevisionCode == 0) {
518 return info.minRevisionCode < version;
519 } else {
520 return (info.minRevisionCode < version) && (info.maxRevisionCode > version);
521 }
522 }
523 }
524
525 /**
526 * Any signature from policy matching with package's signatures is treated as matching.
527 */
528 boolean isAnySignatureMatching(Signature[] fromPackage, Signature[] fromPolicy) {
529 if (fromPackage == null) {
530 return false;
531 }
532 if (fromPolicy == null) {
533 return false;
534 }
535 ArraySet<Signature> setFromPackage = new ArraySet<Signature>();
536 for (Signature sig : fromPackage) {
537 setFromPackage.add(sig);
538 }
539 for (Signature sig : fromPolicy) {
540 if (setFromPackage.contains(sig)) {
541 return true;
542 }
543 }
544 return false;
545 }
546
Keun-young Park4727da32016-05-31 10:00:51 -0700547 /**
Ram Periathiruvadi46a3a3d2018-03-23 16:58:32 -0700548 * Generate a map of whitelisted packages and activities of the form {pkgName, Whitelisted
549 * activities}. The whitelist information can come from a configuration XML resource or from
550 * the apps marking their activities as distraction optimized.
Keun-young Park4727da32016-05-31 10:00:51 -0700551 */
Ram Periathiruvadi46a3a3d2018-03-23 16:58:32 -0700552 private void generateActivityWhitelistMap() {
553 HashMap<String, AppBlockingPackageInfoWrapper> activityWhitelist = new HashMap<>();
554 mConfiguredWhitelist = mContext.getString(R.string.activityWhitelist);
Ram Periathiruvadi46a3a3d2018-03-23 16:58:32 -0700555 // Get the apps/activities that are whitelisted in the configuration XML resource
Yao, Yuxing2a1e1d92019-01-08 11:58:52 -0800556 HashMap<String, Set<String>> configWhitelist = parseConfigList(mConfiguredWhitelist);
Ram Periathiruvadie6e2ac32018-05-02 14:57:46 -0700557 if (configWhitelist == null) {
558 if (DBG_POLICY_CHECK) {
559 Log.w(CarLog.TAG_PACKAGE, "White list null. No apps whitelisted");
560 }
561 return;
562 }
Ram Periathiruvadi46a3a3d2018-03-23 16:58:32 -0700563 // Add the blocking overlay activity to the whitelist, since that needs to run in a
564 // restricted state to communicate the reason an app was blocked.
Keun-young Park4727da32016-05-31 10:00:51 -0700565 Set<String> defaultActivity = new ArraySet<>();
Ram Periathiruvadi402d12e2018-07-11 18:31:13 -0700566 if (mActivityBlockingActivity != null) {
567 defaultActivity.add(mActivityBlockingActivity.getClassName());
568 configWhitelist.put(mActivityBlockingActivity.getPackageName(), defaultActivity);
569 }
Ram Periathiruvadi38388302018-02-22 16:42:49 -0800570
571 List<PackageInfo> packages = mPackageManager.getInstalledPackages(
572 PackageManager.GET_SIGNATURES | PackageManager.GET_ACTIVITIES
573 | PackageManager.MATCH_DIRECT_BOOT_AWARE
574 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
Ram Periathiruvadi46a3a3d2018-03-23 16:58:32 -0700575
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800576 for (PackageInfo info : packages) {
Ram Periathiruvadi38388302018-02-22 16:42:49 -0800577 if (info.applicationInfo == null) {
578 continue;
579 }
580
581 int flags = 0;
Yao, Yuxing2a1e1d92019-01-08 11:58:52 -0800582 Set<String> activities = new ArraySet<>();
Ram Periathiruvadi38388302018-02-22 16:42:49 -0800583
584 if (info.applicationInfo.isSystemApp()
585 || info.applicationInfo.isUpdatedSystemApp()) {
586 flags = AppBlockingPackageInfo.FLAG_SYSTEM_APP;
587 }
588
Ram Periathiruvadi46a3a3d2018-03-23 16:58:32 -0700589 /* 1. Check if all or some of this app is in the <activityWhitelist>
Ram Periathiruvadi38388302018-02-22 16:42:49 -0800590 in config.xml */
591 Set<String> configActivitiesForPackage = configWhitelist.get(info.packageName);
592 if (configActivitiesForPackage != null) {
593 if (DBG_POLICY_CHECK) {
594 Log.d(CarLog.TAG_PACKAGE, info.packageName + " whitelisted");
595 }
596 if (configActivitiesForPackage.size() == 0) {
597 // Whole Pkg has been whitelisted
598 flags |= AppBlockingPackageInfo.FLAG_WHOLE_ACTIVITY;
599 // Add all activities to the whitelist
Yao, Yuxing2a1e1d92019-01-08 11:58:52 -0800600 List<String> activitiesForPackage = getActivitiesInPackage(info);
601 if (activitiesForPackage != null) {
602 activities.addAll(activitiesForPackage);
603 } else {
604 if (DBG_POLICY_CHECK) {
605 Log.d(CarLog.TAG_PACKAGE, info.packageName + ": Activities null");
606 }
Keun-young Park4727da32016-05-31 10:00:51 -0700607 }
608 } else {
Ram Periathiruvadi38388302018-02-22 16:42:49 -0800609 if (DBG_POLICY_CHECK) {
610 Log.d(CarLog.TAG_PACKAGE, "Partially Whitelisted. WL Activities:");
611 for (String a : configActivitiesForPackage) {
612 Log.d(CarLog.TAG_PACKAGE, a);
Keun-young Park4727da32016-05-31 10:00:51 -0700613 }
614 }
Yao, Yuxing2a1e1d92019-01-08 11:58:52 -0800615 activities.addAll(configActivitiesForPackage);
Ram Periathiruvadi38388302018-02-22 16:42:49 -0800616 }
Yao, Yuxing2a1e1d92019-01-08 11:58:52 -0800617 }
618 /* 2. If app is not listed in the config.xml check their Manifest meta-data to
619 see if they have any Distraction Optimized(DO) activities.
620 For non system apps, we check if the app install source was a permittable
621 source. This prevents side-loaded apps to fake DO. Bypass the check
622 for debug builds for development convenience. */
623 if (!isDebugBuild()
624 && !info.applicationInfo.isSystemApp()
625 && !info.applicationInfo.isUpdatedSystemApp()) {
Ram Periathiruvadi38388302018-02-22 16:42:49 -0800626 try {
Yao, Yuxing2a1e1d92019-01-08 11:58:52 -0800627 if (mAllowedAppInstallSources != null) {
628 String installerName = mPackageManager.getInstallerPackageName(
629 info.packageName);
630 if (installerName == null || (installerName != null
631 && !mAllowedAppInstallSources.contains(installerName))) {
632 Log.w(CarLog.TAG_PACKAGE,
633 info.packageName + " not installed from permitted sources "
Oleh Cherpak01b09332019-02-12 15:43:33 +0200634 + (installerName == null ? "NULL" : installerName));
Yao, Yuxing2a1e1d92019-01-08 11:58:52 -0800635 continue;
636 }
637 }
638 } catch (IllegalArgumentException e) {
639 Log.w(CarLog.TAG_PACKAGE, info.packageName + " not installed!");
Ram Periathiruvadi38388302018-02-22 16:42:49 -0800640 continue;
641 }
Yao, Yuxing2a1e1d92019-01-08 11:58:52 -0800642 }
643
644 try {
645 String[] doActivities = CarAppMetadataReader.findDistractionOptimizedActivities(
646 mContext, info.packageName);
647 if (doActivities != null) {
Ram Periathiruvadi38388302018-02-22 16:42:49 -0800648 // Some of the activities in this app are Distraction Optimized.
649 if (DBG_POLICY_CHECK) {
Yao, Yuxing2a1e1d92019-01-08 11:58:52 -0800650 for (String activity : doActivities) {
Ram Periathiruvadi38388302018-02-22 16:42:49 -0800651 Log.d(CarLog.TAG_PACKAGE,
652 "adding " + activity + " from " + info.packageName
653 + " to whitelist");
654 }
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800655 }
Yao, Yuxing2a1e1d92019-01-08 11:58:52 -0800656 activities.addAll(Arrays.asList(doActivities));
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800657 }
Yao, Yuxing2a1e1d92019-01-08 11:58:52 -0800658 } catch (NameNotFoundException e) {
659 Log.w(CarLog.TAG_PACKAGE, "Error reading metadata: " + info.packageName);
660 continue;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800661 }
Yao, Yuxing2a1e1d92019-01-08 11:58:52 -0800662
Ram Periathiruvadi38388302018-02-22 16:42:49 -0800663 // Nothing to add to whitelist
Yao, Yuxing2a1e1d92019-01-08 11:58:52 -0800664 if (activities.isEmpty()) {
Ram Periathiruvadi38388302018-02-22 16:42:49 -0800665 continue;
666 }
667
668 Signature[] signatures;
669 signatures = info.signatures;
670 AppBlockingPackageInfo appBlockingInfo = new AppBlockingPackageInfo(
Yao, Yuxing2a1e1d92019-01-08 11:58:52 -0800671 info.packageName, 0, 0, flags, signatures,
672 activities.toArray(new String[activities.size()]));
Ram Periathiruvadi38388302018-02-22 16:42:49 -0800673 AppBlockingPackageInfoWrapper wrapper = new AppBlockingPackageInfoWrapper(
674 appBlockingInfo, true);
675 activityWhitelist.put(info.packageName, wrapper);
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800676 }
677 synchronized (this) {
Ram Periathiruvadi295954d2018-04-10 18:27:28 -0700678 mActivityWhitelistMap.clear();
Ram Periathiruvadi46a3a3d2018-03-23 16:58:32 -0700679 mActivityWhitelistMap.putAll(activityWhitelist);
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800680 }
681 }
682
Ram Periathiruvadid937c322018-06-13 12:28:12 -0700683 private boolean isDebugBuild() {
684 return Build.IS_USERDEBUG || Build.IS_ENG;
685 }
686
Ram Periathiruvadi46a3a3d2018-03-23 16:58:32 -0700687 /**
688 * Generate a map of blacklisted packages and activities of the form {pkgName, Blacklisted
689 * activities}. The blacklist information comes from a configuration XML resource.
690 */
691 private void generateActivityBlacklistMap() {
692 HashMap<String, AppBlockingPackageInfoWrapper> activityBlacklist = new HashMap<>();
693 mConfiguredBlacklist = mContext.getString(R.string.activityBlacklist);
Ram Periathiruvadie6e2ac32018-05-02 14:57:46 -0700694 if (mConfiguredBlacklist == null) {
695 if (DBG_POLICY_CHECK) {
696 Log.d(CarLog.TAG_PACKAGE, "Null blacklist in config");
697 }
698 return;
699 }
Yao, Yuxing2a1e1d92019-01-08 11:58:52 -0800700 Map<String, Set<String>> configBlacklist = parseConfigList(mConfiguredBlacklist);
Ram Periathiruvadie6e2ac32018-05-02 14:57:46 -0700701 if (configBlacklist == null) {
702 if (DBG_POLICY_CHECK) {
703 Log.w(CarLog.TAG_PACKAGE, "Black list null. No apps blacklisted");
704 }
705 return;
706 }
Ram Periathiruvadi46a3a3d2018-03-23 16:58:32 -0700707
708 for (String pkg : configBlacklist.keySet()) {
Ram Periathiruvadi402d12e2018-07-11 18:31:13 -0700709 if (TextUtils.isEmpty(pkg)) {
710 // This means there is nothing to blacklist
711 Log.d(CarLog.TAG_PACKAGE, "Empty string in blacklist pkg");
712 continue;
713 }
Ram Periathiruvadi46a3a3d2018-03-23 16:58:32 -0700714 int flags = 0;
715 PackageInfo pkgInfo;
Yao, Yuxing2a1e1d92019-01-08 11:58:52 -0800716 Set<String> activities = new ArraySet<>();
Ram Periathiruvadi46a3a3d2018-03-23 16:58:32 -0700717 try {
718 pkgInfo = mPackageManager.getPackageInfo(
719 pkg, PackageManager.GET_ACTIVITIES
720 | PackageManager.GET_SIGNING_CERTIFICATES
721 | PackageManager.MATCH_DIRECT_BOOT_AWARE
722 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
723 } catch (NameNotFoundException e) {
Ram Periathiruvadi402d12e2018-07-11 18:31:13 -0700724 Log.e(CarLog.TAG_PACKAGE, pkg + " not found to blacklist ", e);
Ram Periathiruvadi46a3a3d2018-03-23 16:58:32 -0700725 continue;
726 }
727
728 if (pkgInfo.applicationInfo.isSystemApp()
729 || pkgInfo.applicationInfo.isUpdatedSystemApp()) {
730 flags |= AppBlockingPackageInfo.FLAG_SYSTEM_APP;
731 }
732 Set<String> configActivities = configBlacklist.get(pkg);
733 if (configActivities.size() == 0) {
734 // whole package
735 flags |= AppBlockingPackageInfo.FLAG_WHOLE_ACTIVITY;
Yao, Yuxing2a1e1d92019-01-08 11:58:52 -0800736 List<String> activitiesInPackage = getActivitiesInPackage(pkgInfo);
737 if (activitiesInPackage != null && !activitiesInPackage.isEmpty()) {
738 activities.addAll(activitiesInPackage);
739 }
Ram Periathiruvadi46a3a3d2018-03-23 16:58:32 -0700740 } else {
Yao, Yuxing2a1e1d92019-01-08 11:58:52 -0800741 activities.addAll(configActivities);
Ram Periathiruvadi46a3a3d2018-03-23 16:58:32 -0700742 }
743
Yao, Yuxing2a1e1d92019-01-08 11:58:52 -0800744 if (activities.isEmpty()) {
Ram Periathiruvadi46a3a3d2018-03-23 16:58:32 -0700745 continue;
746 }
747 AppBlockingPackageInfo appBlockingInfo = new AppBlockingPackageInfo(pkg, 0, 0, flags,
Yao, Yuxing2a1e1d92019-01-08 11:58:52 -0800748 pkgInfo.signatures, activities.toArray(new String[activities.size()]));
Ram Periathiruvadi46a3a3d2018-03-23 16:58:32 -0700749 AppBlockingPackageInfoWrapper wrapper = new AppBlockingPackageInfoWrapper(
750 appBlockingInfo, true);
751 activityBlacklist.put(pkg, wrapper);
752 }
753 synchronized (this) {
Ram Periathiruvadi295954d2018-04-10 18:27:28 -0700754 mActivityBlacklistMap.clear();
Ram Periathiruvadi46a3a3d2018-03-23 16:58:32 -0700755 mActivityBlacklistMap.putAll(activityBlacklist);
756 }
757 }
758
759 /**
760 * Parses the given resource and returns a map of packages and activities.
761 * Key is package name and value is list of activities. Empty list implies whole package is
762 * included.
763 */
Ram Periathiruvadie6e2ac32018-05-02 14:57:46 -0700764 @Nullable
Yao, Yuxing2a1e1d92019-01-08 11:58:52 -0800765 private HashMap<String, Set<String>> parseConfigList(String configList) {
Ram Periathiruvadie6e2ac32018-05-02 14:57:46 -0700766 if (configList == null) {
767 return null;
768 }
Ram Periathiruvadi46a3a3d2018-03-23 16:58:32 -0700769 HashMap<String, Set<String>> packageToActivityMap = new HashMap<>();
770 String[] entries = configList.split(PACKAGE_DELIMITER);
771 for (String entry : entries) {
772 String[] packageActivityPair = entry.split(PACKAGE_ACTIVITY_DELIMITER);
773 Set<String> activities = packageToActivityMap.get(packageActivityPair[0]);
774 boolean newPackage = false;
775 if (activities == null) {
776 activities = new ArraySet<>();
777 newPackage = true;
778 packageToActivityMap.put(packageActivityPair[0], activities);
779 }
780 if (packageActivityPair.length == 1) { // whole package
781 activities.clear();
782 } else if (packageActivityPair.length == 2) {
783 // add class name only when the whole package is not whitelisted.
784 if (newPackage || (activities.size() > 0)) {
785 activities.add(packageActivityPair[1]);
786 }
787 }
788 }
789 return packageToActivityMap;
790 }
791
Ram Periathiruvadi38388302018-02-22 16:42:49 -0800792 @Nullable
Yao, Yuxing2a1e1d92019-01-08 11:58:52 -0800793 private List<String> getActivitiesInPackage(PackageInfo info) {
Ram Periathiruvadi38388302018-02-22 16:42:49 -0800794 if (info == null || info.activities == null) {
795 return null;
796 }
797 List<String> activityList = new ArrayList<>();
798 for (ActivityInfo aInfo : info.activities) {
799 activityList.add(aInfo.name);
800 }
Yao, Yuxing2a1e1d92019-01-08 11:58:52 -0800801 return activityList;
Ram Periathiruvadi38388302018-02-22 16:42:49 -0800802 }
803
Ram Periathiruvadi8ef1a202018-03-16 17:49:21 -0700804 /**
805 * Checks if there are any {@link CarAppBlockingPolicyService} and creates a proxy to
806 * bind to them and retrieve the {@link CarAppBlockingPolicy}
807 */
808 @VisibleForTesting
809 public void startAppBlockingPolicies() {
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800810 Intent policyIntent = new Intent();
811 policyIntent.setAction(CarAppBlockingPolicyService.SERVICE_INTERFACE);
812 List<ResolveInfo> policyInfos = mPackageManager.queryIntentServices(policyIntent, 0);
813 if (policyInfos == null) { //no need to wait for service binding and retrieval.
814 mHandler.requestPolicySetting();
815 return;
816 }
817 LinkedList<AppBlockingPolicyProxy> proxies = new LinkedList<>();
818 for (ResolveInfo resolveInfo : policyInfos) {
819 ServiceInfo serviceInfo = resolveInfo.serviceInfo;
820 if (serviceInfo == null) {
821 continue;
822 }
823 if (serviceInfo.isEnabled()) {
824 if (mPackageManager.checkPermission(Car.PERMISSION_CONTROL_APP_BLOCKING,
825 serviceInfo.packageName) != PackageManager.PERMISSION_GRANTED) {
826 continue;
827 }
828 Log.i(CarLog.TAG_PACKAGE, "found policy holding service:" + serviceInfo);
829 AppBlockingPolicyProxy proxy = new AppBlockingPolicyProxy(this, mContext,
830 serviceInfo);
831 proxy.connect();
832 proxies.add(proxy);
833 }
834 }
835 synchronized (this) {
836 mProxies = proxies;
837 }
838 }
839
840 public void onPolicyConnectionAndSet(AppBlockingPolicyProxy proxy,
841 CarAppBlockingPolicy policy) {
842 doHandlePolicyConnection(proxy, policy);
843 }
844
845 public void onPolicyConnectionFailure(AppBlockingPolicyProxy proxy) {
846 doHandlePolicyConnection(proxy, null);
847 }
848
849 private void doHandlePolicyConnection(AppBlockingPolicyProxy proxy,
850 CarAppBlockingPolicy policy) {
851 boolean shouldSetPolicy = false;
852 synchronized (this) {
853 if (mProxies == null) {
854 proxy.disconnect();
855 return;
856 }
857 mProxies.remove(proxy);
858 if (mProxies.size() == 0) {
859 shouldSetPolicy = true;
860 mProxies = null;
861 }
862 }
863 try {
864 if (policy != null) {
865 if (DBG_POLICY_SET) {
866 Log.i(CarLog.TAG_PACKAGE, "policy setting from policy service:" +
867 proxy.getPackageName());
868 }
869 doSetAppBlockingPolicy(proxy.getPackageName(), policy, 0, false /*setNow*/);
870 }
871 } finally {
872 proxy.disconnect();
873 if (shouldSetPolicy) {
874 mHandler.requestPolicySetting();
875 }
876 }
877 }
878
879 @Override
880 public void dump(PrintWriter writer) {
881 synchronized (this) {
882 writer.println("*PackageManagementService*");
Keun-young Park4727da32016-05-31 10:00:51 -0700883 writer.println("mEnableActivityBlocking:" + mEnableActivityBlocking);
Ram Periathiruvadie6e2ac32018-05-02 14:57:46 -0700884 writer.println("mHasParsedPackages:" + mHasParsedPackages);
885 writer.println("mBootLockedIntentRx:" + mBootLockedIntentRx);
Ram Periathiruvadi2da6d0e2018-01-26 18:02:10 -0800886 writer.println("ActivityRestricted:" + mUxRestrictionsListener.isRestricted());
Yao, Yuxingd1d6a372018-05-08 10:37:43 -0700887 writer.println(String.join("\n", mBlockedActivityLogs));
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800888 writer.print(dumpPoliciesLocked(true));
889 }
890 }
891
Andreas Gampe985ca2f2018-02-09 12:57:54 -0800892 @GuardedBy("this")
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800893 private String dumpPoliciesLocked(boolean dumpAll) {
894 StringBuilder sb = new StringBuilder();
895 if (dumpAll) {
896 sb.append("**System white list**\n");
Ram Periathiruvadi46a3a3d2018-03-23 16:58:32 -0700897 for (AppBlockingPackageInfoWrapper wrapper : mActivityWhitelistMap.values()) {
898 sb.append(wrapper.toString() + "\n");
899 }
900 sb.append("**System Black list**\n");
901 for (AppBlockingPackageInfoWrapper wrapper : mActivityBlacklistMap.values()) {
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800902 sb.append(wrapper.toString() + "\n");
903 }
904 }
905 sb.append("**Client Policies**\n");
906 for (Entry<String, ClientPolicy> entry : mClientPolicies.entrySet()) {
907 sb.append("Client:" + entry.getKey() + "\n");
908 sb.append(" whitelists:\n");
909 for (AppBlockingPackageInfoWrapper wrapper : entry.getValue().whitelistsMap.values()) {
910 sb.append(wrapper.toString() + "\n");
911 }
912 sb.append(" blacklists:\n");
913 for (AppBlockingPackageInfoWrapper wrapper : entry.getValue().blacklistsMap.values()) {
914 sb.append(wrapper.toString() + "\n");
915 }
916 }
917 sb.append("**Unprocessed policy services**\n");
918 if (mProxies != null) {
919 for (AppBlockingPolicyProxy proxy : mProxies) {
920 sb.append(proxy.toString() + "\n");
921 }
922 }
Ram Periathiruvadi46a3a3d2018-03-23 16:58:32 -0700923 sb.append("**Whitelist string in resource**\n");
924 sb.append(mConfiguredWhitelist + "\n");
925
926 sb.append("**Blacklist string in resource**\n");
927 sb.append(mConfiguredBlacklist + "\n");
Keun-young Park98960812016-10-04 12:50:54 -0700928
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800929 return sb.toString();
930 }
931
Keun-young Park4727da32016-05-31 10:00:51 -0700932 private void blockTopActivityIfNecessary(TopTaskInfoContainer topTask) {
Yao, Yuxingcfcc59f2019-03-05 16:35:47 -0800933 // Only block activities launched on default display.
934 if (topTask.displayId != Display.DEFAULT_DISPLAY) {
935 return;
936 }
937 if (!mUxRestrictionsListener.isRestricted()) {
Keun-young Park4727da32016-05-31 10:00:51 -0700938 return;
939 }
940 doBlockTopActivityIfNotAllowed(topTask);
941 }
942
943 private void doBlockTopActivityIfNotAllowed(TopTaskInfoContainer topTask) {
Ram Periathiruvadi2da6d0e2018-01-26 18:02:10 -0800944 if (topTask.topActivity == null) {
945 return;
946 }
Ram Periathiruvadie154f582018-03-21 21:53:27 -0700947 boolean allowed = isActivityDistractionOptimized(
Keun-young Park4727da32016-05-31 10:00:51 -0700948 topTask.topActivity.getPackageName(),
949 topTask.topActivity.getClassName());
950 if (DBG_POLICY_ENFORCEMENT) {
951 Log.i(CarLog.TAG_PACKAGE, "new activity:" + topTask.toString() + " allowed:" + allowed);
952 }
Ram Periathiruvadibf0eab72018-02-06 12:32:43 -0800953 if (allowed) {
954 return;
955 }
Ram Periathiruvadie6e2ac32018-05-02 14:57:46 -0700956 synchronized (this) {
Ram Periathiruvadibf0eab72018-02-06 12:32:43 -0800957 if (!mEnableActivityBlocking) {
958 Log.d(CarLog.TAG_PACKAGE, "Current activity " + topTask.topActivity +
Ram Periathiruvadie6e2ac32018-05-02 14:57:46 -0700959 " not allowed, blocking disabled. Number of tasks in stack:"
960 + topTask.stackInfo.taskIds.length);
Ram Periathiruvadibf0eab72018-02-06 12:32:43 -0800961 return;
962 }
963 }
Ram Periathiruvadi38388302018-02-22 16:42:49 -0800964 if (DBG_POLICY_CHECK) {
Keun-young Park4727da32016-05-31 10:00:51 -0700965 Log.i(CarLog.TAG_PACKAGE, "Current activity " + topTask.topActivity +
966 " not allowed, will block, number of tasks in stack:" +
967 topTask.stackInfo.taskIds.length);
Keun-young Park4727da32016-05-31 10:00:51 -0700968 }
Yao, Yuxingd1d6a372018-05-08 10:37:43 -0700969
Yao, Yuxing14e83b42018-10-29 18:29:56 -0700970 // Figure out the root activity of blocked task.
971 String taskRootActivity = null;
Yao, Yuxingd1d6a372018-05-08 10:37:43 -0700972 for (int i = 0; i < topTask.stackInfo.taskIds.length; i++) {
973 // topTask.taskId is the task that should be blocked.
974 if (topTask.stackInfo.taskIds[i] == topTask.taskId) {
975 // stackInfo represents an ActivityStack. Its fields taskIds and taskNames
976 // are 1:1 mapped, where taskNames is the name of root activity in this task.
Yao, Yuxing14e83b42018-10-29 18:29:56 -0700977 taskRootActivity = topTask.stackInfo.taskNames[i];
Yao, Yuxingd1d6a372018-05-08 10:37:43 -0700978 break;
979 }
980 }
Yao, Yuxing14e83b42018-10-29 18:29:56 -0700981
982 boolean isRootDO = false;
983 if (taskRootActivity != null) {
984 ComponentName componentName = ComponentName.unflattenFromString(taskRootActivity);
985 isRootDO = isActivityDistractionOptimized(
986 componentName.getPackageName(), componentName.getClassName());
987 }
988
989 Intent newActivityIntent = createBlockingActivityIntent(
990 mActivityBlockingActivity, topTask.topActivity.flattenToShortString(),
991 topTask.taskId, taskRootActivity, isRootDO);
992
993 // Intent contains all info to debug what is blocked - log into both logcat and dumpsys.
994 String log = "Starting blocking activity with intent: " + newActivityIntent.toUri(0);
995 if (Log.isLoggable(CarLog.TAG_PACKAGE, Log.INFO)) {
996 Log.i(CarLog.TAG_PACKAGE, log);
997 }
998 addLog(log);
Ram Periathiruvadi38388302018-02-22 16:42:49 -0800999 mSystemActivityMonitoringService.blockActivity(topTask, newActivityIntent);
Keun-young Park4727da32016-05-31 10:00:51 -07001000 }
1001
Yao, Yuxing14e83b42018-10-29 18:29:56 -07001002 /**
1003 * Creates an intent to start blocking activity.
1004 *
1005 * @param blockingActivity the activity to launch
1006 * @param blockedActivity the activity being blocked
1007 * @param blockedTaskId the blocked task id, which contains the blocked activity
1008 * @param taskRootActivity root activity of the blocked task
1009 *
1010 * @return an intent to launch the blocking activity.
1011 */
1012 private static Intent createBlockingActivityIntent(ComponentName blockingActivity,
1013 String blockedActivity, int blockedTaskId, String taskRootActivity, boolean isRootDo) {
1014 Intent newActivityIntent = new Intent();
1015 newActivityIntent.setComponent(blockingActivity);
1016 newActivityIntent.putExtra(
1017 BLOCKING_INTENT_EXTRA_BLOCKED_ACTIVITY_NAME, blockedActivity);
1018 newActivityIntent.putExtra(
1019 BLOCKING_INTENT_EXTRA_BLOCKED_TASK_ID, blockedTaskId);
1020 newActivityIntent.putExtra(
1021 BLOCKING_INTENT_EXTRA_ROOT_ACTIVITY_NAME, taskRootActivity);
1022 newActivityIntent.putExtra(
1023 BLOCKING_INTENT_EXTRA_IS_ROOT_ACTIVITY_DO, isRootDo);
Yao, Yuxingcfcc59f2019-03-05 16:35:47 -08001024
Yao, Yuxing14e83b42018-10-29 18:29:56 -07001025 return newActivityIntent;
1026 }
1027
Keun-young Park4727da32016-05-31 10:00:51 -07001028 private void blockTopActivitiesIfNecessary() {
Ram Periathiruvadi2da6d0e2018-01-26 18:02:10 -08001029 boolean restricted = mUxRestrictionsListener.isRestricted();
Keun-young Park4727da32016-05-31 10:00:51 -07001030 if (!restricted) {
1031 return;
1032 }
1033 List<TopTaskInfoContainer> topTasks = mSystemActivityMonitoringService.getTopTasks();
1034 for (TopTaskInfoContainer topTask : topTasks) {
1035 doBlockTopActivityIfNotAllowed(topTask);
1036 }
1037 }
1038
Ram Periathiruvadicdee1202018-07-17 18:01:31 -07001039 /**
1040 * Enable/Disable activity blocking by correspondingly enabling/disabling broadcasting UXR
1041 * changes in {@link CarUxRestrictionsManagerService}. This is only available in
1042 * engineering builds for development convenience.
1043 *
1044 */
Ram Periathiruvadia6e0d9b2018-04-25 20:19:22 -07001045 @Override
Ram Periathiruvadibf0eab72018-02-06 12:32:43 -08001046 public synchronized void setEnableActivityBlocking(boolean enable) {
Ram Periathiruvadicdee1202018-07-17 18:01:31 -07001047 if (!isDebugBuild()) {
1048 Log.e(CarLog.TAG_PACKAGE, "Cannot enable/disable activity blocking");
1049 return;
1050 }
Ram Periathiruvadia6e0d9b2018-04-25 20:19:22 -07001051 // Check if the caller has the same signature as that of the car service.
1052 if (mPackageManager.checkSignatures(Process.myUid(), Binder.getCallingUid())
1053 != PackageManager.SIGNATURE_MATCH) {
1054 throw new SecurityException(
1055 "Caller " + mPackageManager.getNameForUid(Binder.getCallingUid())
1056 + " does not have the right signature");
1057 }
Ram Periathiruvadicdee1202018-07-17 18:01:31 -07001058 mCarUxRestrictionsService.setUxRChangeBroadcastEnabled(enable);
Ram Periathiruvadibf0eab72018-02-06 12:32:43 -08001059 }
1060
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001061 /**
Ram Periathiruvadi38388302018-02-22 16:42:49 -08001062 * Get the distraction optimized activities for the given package.
1063 *
1064 * @param pkgName Name of the package
1065 * @return Array of the distraction optimized activities in the package
1066 */
1067 @Nullable
1068 public String[] getDistractionOptimizedActivities(String pkgName) {
1069 try {
1070 return CarAppMetadataReader.findDistractionOptimizedActivities(mContext, pkgName);
1071 } catch (NameNotFoundException e) {
1072 return null;
1073 }
1074 }
Ram Periathiruvadie6e2ac32018-05-02 14:57:46 -07001075
Ram Periathiruvadi38388302018-02-22 16:42:49 -08001076 /**
Yao, Yuxingd1d6a372018-05-08 10:37:43 -07001077 * Append one line of log for dumpsys.
1078 *
1079 * <p>Maintains the size of log by {@link #LOG_SIZE} and appends tag and timestamp to the line.
1080 */
1081 private void addLog(String log) {
1082 while (mBlockedActivityLogs.size() >= LOG_SIZE) {
1083 mBlockedActivityLogs.remove();
1084 }
1085 StringBuffer sb = new StringBuffer()
1086 .append(CarLog.TAG_PACKAGE).append(':')
1087 .append(DateFormat.format(
1088 "MM-dd HH:mm:ss", System.currentTimeMillis())).append(": ")
1089 .append(log);
1090 mBlockedActivityLogs.add(sb.toString());
1091 }
1092
1093 /**
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001094 * Reading policy and setting policy can take time. Run it in a separate handler thread.
1095 */
1096 private class PackageHandler extends Handler {
1097 private final int MSG_INIT = 0;
Ram Periathiruvadi38388302018-02-22 16:42:49 -08001098 private final int MSG_PARSE_PKG = 1;
1099 private final int MSG_SET_POLICY = 2;
1100 private final int MSG_UPDATE_POLICY = 3;
1101 private final int MSG_RELEASE = 4;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001102
1103 private PackageHandler(Looper looper) {
1104 super(looper);
1105 }
1106
1107 private void requestInit() {
1108 Message msg = obtainMessage(MSG_INIT);
1109 sendMessage(msg);
1110 }
1111
1112 private void requestRelease() {
1113 removeMessages(MSG_INIT);
1114 removeMessages(MSG_SET_POLICY);
1115 removeMessages(MSG_UPDATE_POLICY);
Keun-young Park6dcc50b2016-10-10 19:01:11 -07001116 Message msg = obtainMessage(MSG_RELEASE);
1117 sendMessage(msg);
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001118 }
1119
1120 private void requestPolicySetting() {
1121 Message msg = obtainMessage(MSG_SET_POLICY);
1122 sendMessage(msg);
1123 }
1124
1125 private void requestUpdatingPolicy(String packageName, CarAppBlockingPolicy policy,
1126 int flags) {
1127 Pair<String, CarAppBlockingPolicy> pair = new Pair<>(packageName, policy);
1128 Message msg = obtainMessage(MSG_UPDATE_POLICY, flags, 0, pair);
1129 sendMessage(msg);
1130 }
1131
Ram Periathiruvadi295954d2018-04-10 18:27:28 -07001132 private void requestParsingInstalledPkgs(long delayMs) {
Ram Periathiruvadi38388302018-02-22 16:42:49 -08001133 Message msg = obtainMessage(MSG_PARSE_PKG);
Ram Periathiruvadi295954d2018-04-10 18:27:28 -07001134 if (delayMs == 0) {
1135 sendMessage(msg);
1136 } else {
1137 sendMessageDelayed(msg, delayMs);
1138 }
Ram Periathiruvadi38388302018-02-22 16:42:49 -08001139 }
1140
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001141 @Override
1142 public void handleMessage(Message msg) {
1143 switch (msg.what) {
1144 case MSG_INIT:
1145 doHandleInit();
1146 break;
Ram Periathiruvadi38388302018-02-22 16:42:49 -08001147 case MSG_PARSE_PKG:
Ram Periathiruvadi295954d2018-04-10 18:27:28 -07001148 removeMessages(MSG_PARSE_PKG);
Ram Periathiruvadi38388302018-02-22 16:42:49 -08001149 doParseInstalledPackages();
1150 break;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001151 case MSG_SET_POLICY:
1152 doSetPolicy();
1153 break;
1154 case MSG_UPDATE_POLICY:
1155 Pair<String, CarAppBlockingPolicy> pair =
1156 (Pair<String, CarAppBlockingPolicy>) msg.obj;
1157 doUpdatePolicy(pair.first, pair.second, msg.arg1);
1158 break;
Keun-young Park6dcc50b2016-10-10 19:01:11 -07001159 case MSG_RELEASE:
1160 doHandleRelease();
1161 break;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001162 }
1163 }
1164 }
1165
1166 private static class AppBlockingPackageInfoWrapper {
1167 private final AppBlockingPackageInfo info;
1168 /**
1169 * Whether the current info is matching with the target package in system. Mismatch can
1170 * happen for version out of range or signature mismatch.
1171 */
1172 private boolean isMatching;
1173
1174 private AppBlockingPackageInfoWrapper(AppBlockingPackageInfo info, boolean isMatching) {
Ram Periathiruvadie6e2ac32018-05-02 14:57:46 -07001175 this.info = info;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001176 this.isMatching = isMatching;
1177 }
1178
1179 @Override
1180 public String toString() {
1181 return "AppBlockingPackageInfoWrapper [info=" + info + ", isMatching=" + isMatching +
1182 "]";
1183 }
1184 }
1185
1186 /**
1187 * Client policy holder per each client. Should be accessed with CarpackageManagerService.this
1188 * held.
1189 */
1190 private static class ClientPolicy {
1191 private final HashMap<String, AppBlockingPackageInfoWrapper> whitelistsMap =
1192 new HashMap<>();
1193 private final HashMap<String, AppBlockingPackageInfoWrapper> blacklistsMap =
1194 new HashMap<>();
1195
1196 private void replaceWhitelists(AppBlockingPackageInfoWrapper[] whitelists) {
1197 whitelistsMap.clear();
1198 addToWhitelists(whitelists);
1199 }
1200
1201 private void addToWhitelists(AppBlockingPackageInfoWrapper[] whitelists) {
1202 if (whitelists == null) {
1203 return;
1204 }
1205 for (AppBlockingPackageInfoWrapper wrapper : whitelists) {
1206 if (wrapper != null) {
1207 whitelistsMap.put(wrapper.info.packageName, wrapper);
1208 }
1209 }
1210 }
1211
1212 private void removeWhitelists(AppBlockingPackageInfoWrapper[] whitelists) {
1213 if (whitelists == null) {
1214 return;
1215 }
1216 for (AppBlockingPackageInfoWrapper wrapper : whitelists) {
1217 if (wrapper != null) {
1218 whitelistsMap.remove(wrapper.info.packageName);
1219 }
1220 }
1221 }
1222
1223 private void replaceBlacklists(AppBlockingPackageInfoWrapper[] blacklists) {
1224 blacklistsMap.clear();
1225 addToBlacklists(blacklists);
1226 }
1227
1228 private void addToBlacklists(AppBlockingPackageInfoWrapper[] blacklists) {
1229 if (blacklists == null) {
1230 return;
1231 }
1232 for (AppBlockingPackageInfoWrapper wrapper : blacklists) {
1233 if (wrapper != null) {
1234 blacklistsMap.put(wrapper.info.packageName, wrapper);
1235 }
1236 }
1237 }
1238
1239 private void removeBlacklists(AppBlockingPackageInfoWrapper[] blacklists) {
1240 if (blacklists == null) {
1241 return;
1242 }
1243 for (AppBlockingPackageInfoWrapper wrapper : blacklists) {
1244 if (wrapper != null) {
1245 blacklistsMap.remove(wrapper.info.packageName);
1246 }
1247 }
1248 }
1249 }
Keun-young Park4727da32016-05-31 10:00:51 -07001250
1251 private class ActivityLaunchListener
Ram Periathiruvadie6e2ac32018-05-02 14:57:46 -07001252 implements SystemActivityMonitoringService.ActivityLaunchListener {
Keun-young Park4727da32016-05-31 10:00:51 -07001253 @Override
1254 public void onActivityLaunch(TopTaskInfoContainer topTask) {
1255 blockTopActivityIfNecessary(topTask);
1256 }
1257 }
1258
Ram Periathiruvadi2da6d0e2018-01-26 18:02:10 -08001259 /**
1260 * Listens to the UX restrictions from {@link CarUxRestrictionsManagerService} and initiates
1261 * checking if the foreground Activity should be blocked.
1262 */
1263 private class UxRestrictionsListener extends ICarUxRestrictionsChangeListener.Stub {
1264 @GuardedBy("this")
1265 @Nullable
1266 private CarUxRestrictions mCurrentUxRestrictions;
1267 private final CarUxRestrictionsManagerService uxRestrictionsService;
Keun-young Park4727da32016-05-31 10:00:51 -07001268
Ram Periathiruvadi2da6d0e2018-01-26 18:02:10 -08001269 public UxRestrictionsListener(CarUxRestrictionsManagerService service) {
1270 uxRestrictionsService = service;
1271 mCurrentUxRestrictions = uxRestrictionsService.getCurrentUxRestrictions();
1272 }
1273
1274 @Override
1275 public void onUxRestrictionsChanged(CarUxRestrictions restrictions) {
1276 if (DBG_POLICY_CHECK) {
1277 Log.d(CarLog.TAG_PACKAGE, "Received uxr restrictions: "
1278 + restrictions.isRequiresDistractionOptimization()
1279 + " : " + restrictions.getActiveRestrictions());
1280 }
Ram Periathiruvadic57678d2018-04-23 09:18:33 -07001281 // We are not handling the restrictions until we know what is allowed and what is not.
1282 // This is to handle some situations, where car service is ready and getting sensor
1283 // data but we haven't received the boot complete intents.
1284 if (!mHasParsedPackages) {
1285 return;
1286 }
1287
Keun-young Park4727da32016-05-31 10:00:51 -07001288 synchronized (this) {
Ram Periathiruvadi2da6d0e2018-01-26 18:02:10 -08001289 mCurrentUxRestrictions = new CarUxRestrictions(restrictions);
1290 }
1291 checkIfTopActivityNeedsBlocking();
1292 }
1293
1294 private void checkIfTopActivityNeedsBlocking() {
1295 boolean shouldCheck = false;
1296 synchronized (this) {
1297 if (mCurrentUxRestrictions != null
1298 && mCurrentUxRestrictions.isRequiresDistractionOptimization()) {
1299 shouldCheck = true;
Keun-young Park4727da32016-05-31 10:00:51 -07001300 }
1301 }
Ram Periathiruvadi2da6d0e2018-01-26 18:02:10 -08001302 if (DBG_POLICY_CHECK) {
1303 Log.d(CarLog.TAG_PACKAGE, "block?: " + shouldCheck);
1304 }
1305 if (shouldCheck) {
Keun-young Park4727da32016-05-31 10:00:51 -07001306 blockTopActivitiesIfNecessary();
1307 }
1308 }
1309
1310 private synchronized boolean isRestricted() {
Ram Periathiruvadi2da6d0e2018-01-26 18:02:10 -08001311 // if current restrictions is null, try querying the service, once.
1312 if (mCurrentUxRestrictions == null) {
1313 mCurrentUxRestrictions = uxRestrictionsService.getCurrentUxRestrictions();
1314 }
1315 if (mCurrentUxRestrictions != null) {
1316 return mCurrentUxRestrictions.isRequiresDistractionOptimization();
1317 }
1318 // If restriction information is still not available (could happen during bootup),
1319 // return not restricted. This maintains parity with previous implementation but needs
1320 // a revisit as we test more.
1321 return false;
Keun-young Park4727da32016-05-31 10:00:51 -07001322 }
1323 }
Ram Periathiruvadi38388302018-02-22 16:42:49 -08001324
1325 /**
Ram Periathiruvadie6e2ac32018-05-02 14:57:46 -07001326 * Listens to the Boot intent to initiate parsing installed packages.
Ram Periathiruvadi38388302018-02-22 16:42:49 -08001327 */
Ram Periathiruvadie6e2ac32018-05-02 14:57:46 -07001328 private class BootEventReceiver extends BroadcastReceiver {
Ram Periathiruvadi38388302018-02-22 16:42:49 -08001329 @Override
1330 public void onReceive(Context context, Intent intent) {
Ram Periathiruvadi295954d2018-04-10 18:27:28 -07001331 if (intent == null || intent.getAction() == null) {
1332 return;
1333 }
Ram Periathiruvadie6e2ac32018-05-02 14:57:46 -07001334 if (DBG_POLICY_CHECK) {
1335 Log.d(CarLog.TAG_PACKAGE, "BootEventReceiver Received " + intent.getAction());
1336 }
1337 if (Intent.ACTION_LOCKED_BOOT_COMPLETED.equals(intent.getAction())) {
Ram Periathiruvadi295954d2018-04-10 18:27:28 -07001338 mHandler.requestParsingInstalledPkgs(0);
Ram Periathiruvadie6e2ac32018-05-02 14:57:46 -07001339 mBootLockedIntentRx = true;
1340 }
1341 }
1342 }
1343
1344 /**
1345 * Listens to the package install/uninstall events to know when to initiate parsing
1346 * installed packages.
1347 */
1348 private class PackageParsingEventReceiver extends BroadcastReceiver {
1349 private static final long PACKAGE_PARSING_DELAY_MS = 500;
1350
1351 @Override
1352 public void onReceive(Context context, Intent intent) {
1353 if (intent == null || intent.getAction() == null) {
1354 return;
1355 }
1356 if (DBG_POLICY_CHECK) {
1357 Log.d(CarLog.TAG_PACKAGE,
1358 "PackageParsingEventReceiver Received " + intent.getAction());
1359 }
1360 String action = intent.getAction();
1361 if (isPackageManagerAction(action)) {
Ram Periathiruvadi295954d2018-04-10 18:27:28 -07001362 // send a delayed message so if we received multiple related intents, we parse
1363 // only once.
1364 logEventChange(intent);
1365 mHandler.requestParsingInstalledPkgs(PACKAGE_PARSING_DELAY_MS);
1366 }
1367 }
1368
1369 private boolean isPackageManagerAction(String action) {
1370 return mPackageManagerActions.indexOf(action) != -1;
1371 }
1372
1373 /**
1374 * Convenience log function to log what changed. Logs only when more debug logs
1375 * are needed - DBG_POLICY_CHECK needs to be true
1376 */
1377 private void logEventChange(Intent intent) {
1378 if (!DBG_POLICY_CHECK || intent == null) {
1379 return;
1380 }
1381
1382 String packageName = intent.getData().getSchemeSpecificPart();
1383 Log.d(CarLog.TAG_PACKAGE, "Pkg Changed:" + packageName);
1384 String action = intent.getAction();
1385 if (action == null) {
1386 return;
1387 }
1388 if (action.equals(Intent.ACTION_PACKAGE_CHANGED)) {
1389 Log.d(CarLog.TAG_PACKAGE, "Changed components");
1390 String[] cc = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST);
1391 if (cc != null) {
1392 for (String c : cc) {
1393 Log.d(CarLog.TAG_PACKAGE, c);
1394 }
1395 }
1396 } else if (action.equals(Intent.ACTION_PACKAGE_REMOVED)
1397 || action.equals(Intent.ACTION_PACKAGE_ADDED)) {
1398 Log.d(CarLog.TAG_PACKAGE, action + " Replacing?: " + intent.getBooleanExtra(
1399 Intent.EXTRA_REPLACING, false));
Ram Periathiruvadi38388302018-02-22 16:42:49 -08001400 }
1401 }
1402 }
Keun-young Park4aeb4bf2015-12-08 18:31:33 -08001403}