blob: 8a3bd94c12e9d4ead7871a83f9bcc328a91a8912 [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 */
16package com.android.car.pm;
17
Keun-young Park4727da32016-05-31 10:00:51 -070018import android.app.ActivityManager.StackInfo;
Keun-young Parke54ac272016-02-16 19:02:18 -080019import android.car.Car;
20import android.car.content.pm.AppBlockingPackageInfo;
21import android.car.content.pm.CarAppBlockingPolicy;
22import android.car.content.pm.CarAppBlockingPolicyService;
23import android.car.content.pm.CarPackageManager;
24import android.car.content.pm.ICarPackageManager;
Keun-young Park4727da32016-05-31 10:00:51 -070025import android.car.hardware.CarSensorEvent;
26import android.car.hardware.CarSensorManager;
27import android.car.hardware.ICarSensorEventListener;
28import android.content.ComponentName;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -080029import android.content.Context;
30import android.content.Intent;
31import android.content.pm.PackageInfo;
32import android.content.pm.PackageManager;
33import android.content.pm.PackageManager.NameNotFoundException;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -080034import android.content.pm.ResolveInfo;
Pavel Maltsev0d07c762016-11-03 16:40:15 -070035import android.content.pm.ServiceInfo;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -080036import android.content.pm.Signature;
Keun-young Park4727da32016-05-31 10:00:51 -070037import android.content.res.Resources;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -080038import android.os.Handler;
39import android.os.HandlerThread;
40import android.os.Looper;
41import android.os.Message;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -080042import android.util.ArraySet;
43import android.util.Log;
44import android.util.Pair;
45
46import com.android.car.CarLog;
Keun-young Park4727da32016-05-31 10:00:51 -070047import com.android.car.CarSensorService;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -080048import com.android.car.CarServiceBase;
49import com.android.car.CarServiceUtils;
Keun-young Park4727da32016-05-31 10:00:51 -070050import com.android.car.R;
51import com.android.car.SystemActivityMonitoringService;
52import com.android.car.SystemActivityMonitoringService.TopTaskInfoContainer;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -080053import com.android.car.pm.CarAppMetadataReader.CarAppMetadataInfo;
54import com.android.internal.annotations.GuardedBy;
55
56import java.io.PrintWriter;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -080057import java.util.HashMap;
58import java.util.LinkedList;
59import java.util.List;
60import java.util.Map.Entry;
Keun-young Park4727da32016-05-31 10:00:51 -070061import java.util.Set;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -080062
Keun-young Parkf9215202016-10-10 12:34:08 -070063//TODO monitor app installing and refresh policy, bug: 31970400
Keun-young Park4aeb4bf2015-12-08 18:31:33 -080064
65public class CarPackageManagerService extends ICarPackageManager.Stub implements CarServiceBase {
Vitalii Tomkiv1b1247b2016-09-30 11:27:19 -070066 static final boolean DBG_POLICY_SET = false;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -080067 static final boolean DBG_POLICY_CHECK = false;
Vitalii Tomkiv1b1247b2016-09-30 11:27:19 -070068 static final boolean DBG_POLICY_ENFORCEMENT = false;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -080069
70 private final Context mContext;
Keun-young Park4727da32016-05-31 10:00:51 -070071 private final SystemActivityMonitoringService mSystemActivityMonitoringService;
72 private final CarSensorService mSensorService;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -080073 private final PackageManager mPackageManager;
74
75 private final HandlerThread mHandlerThread;
76 private final PackageHandler mHandler;
77
Keun-young Park98960812016-10-04 12:50:54 -070078 private String mDefauiltActivityWhitelist;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -080079 /**
80 * Hold policy set from policy service or client.
81 * Key: packageName of policy service
82 */
83 @GuardedBy("this")
84 private final HashMap<String, ClientPolicy> mClientPolicies =
85 new HashMap<>();
86 @GuardedBy("this")
87 private HashMap<String, AppBlockingPackageInfoWrapper> mSystemWhitelists = new HashMap<>();
88 @GuardedBy("this")
89 private LinkedList<AppBlockingPolicyProxy> mProxies;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -080090
91 @GuardedBy("this")
92 private final LinkedList<CarAppBlockingPolicy> mWaitingPolicies = new LinkedList<>();
93
Keun-young Park4727da32016-05-31 10:00:51 -070094 private final boolean mEnableActivityBlocking;
95 private final ComponentName mActivityBlockingActivity;
96
97 private final ActivityLaunchListener mActivityLaunchListener = new ActivityLaunchListener();
98 private final SensorListener mDrivingStateListener = new SensorListener();
99
100 public CarPackageManagerService(Context context, CarSensorService sensorService,
101 SystemActivityMonitoringService systemActivityMonitoringService) {
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800102 mContext = context;
Keun-young Park4727da32016-05-31 10:00:51 -0700103 mSensorService = sensorService;
104 mSystemActivityMonitoringService = systemActivityMonitoringService;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800105 mPackageManager = mContext.getPackageManager();
106 mHandlerThread = new HandlerThread(CarLog.TAG_PACKAGE);
107 mHandlerThread.start();
108 mHandler = new PackageHandler(mHandlerThread.getLooper());
Keun-young Park4727da32016-05-31 10:00:51 -0700109 Resources res = context.getResources();
110 mEnableActivityBlocking = res.getBoolean(R.bool.enableActivityBlockingForSafety);
111 String blockingActivity = res.getString(R.string.activityBlockingActivity);
112 mActivityBlockingActivity = ComponentName.unflattenFromString(blockingActivity);
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800113 }
114
115 @Override
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800116 public void setAppBlockingPolicy(String packageName, CarAppBlockingPolicy policy, int flags) {
117 if (DBG_POLICY_SET) {
118 Log.i(CarLog.TAG_PACKAGE, "policy setting from binder call, client:" + packageName);
119 }
120 doSetAppBlockingPolicy(packageName, policy, flags, true /*setNow*/);
121 }
122
123 private void doSetAppBlockingPolicy(String packageName, CarAppBlockingPolicy policy, int flags,
124 boolean setNow) {
125 if (mContext.checkCallingOrSelfPermission(Car.PERMISSION_CONTROL_APP_BLOCKING)
126 != PackageManager.PERMISSION_GRANTED) {
127 throw new SecurityException(
128 "requires permission " + Car.PERMISSION_CONTROL_APP_BLOCKING);
129 }
130 CarServiceUtils.assertPakcageName(mContext, packageName);
131 if (policy == null) {
132 throw new IllegalArgumentException("policy cannot be null");
133 }
134 if ((flags & CarPackageManager.FLAG_SET_POLICY_ADD) != 0 &&
135 (flags & CarPackageManager.FLAG_SET_POLICY_REMOVE) != 0) {
136 throw new IllegalArgumentException(
137 "Cannot set both FLAG_SET_POLICY_ADD and FLAG_SET_POLICY_REMOVE flag");
138 }
139 mHandler.requestUpdatingPolicy(packageName, policy, flags);
140 if (setNow) {
141 mHandler.requestPolicySetting();
142 if ((flags & CarPackageManager.FLAG_SET_POLICY_WAIT_FOR_CHANGE) != 0) {
143 synchronized (policy) {
144 try {
145 policy.wait();
146 } catch (InterruptedException e) {
147 }
148 }
149 }
150 }
151 }
152
153 @Override
154 public boolean isActivityAllowedWhileDriving(String packageName, String className) {
155 assertPackageAndClassName(packageName, className);
156 synchronized (this) {
157 if (DBG_POLICY_CHECK) {
158 Log.i(CarLog.TAG_PACKAGE, "isActivityAllowedWhileDriving" +
159 dumpPoliciesLocked(false));
160 }
161 AppBlockingPackageInfo info = searchFromBlacklistsLocked(packageName);
162 if (info != null) {
163 return false;
164 }
165 return isActivityInWhitelistsLocked(packageName, className);
166 }
167 }
168
169 @Override
170 public boolean isServiceAllowedWhileDriving(String packageName, String className) {
171 if (packageName == null) {
172 throw new IllegalArgumentException("Package name null");
173 }
174 synchronized (this) {
175 if (DBG_POLICY_CHECK) {
176 Log.i(CarLog.TAG_PACKAGE, "isServiceAllowedWhileDriving" +
177 dumpPoliciesLocked(false));
178 }
179 AppBlockingPackageInfo info = searchFromBlacklistsLocked(packageName);
180 if (info != null) {
181 return false;
182 }
183 info = searchFromWhitelistsLocked(packageName);
184 if (info != null) {
185 return true;
186 }
187 }
188 return false;
189 }
190
Keun-young Park4727da32016-05-31 10:00:51 -0700191 @Override
192 public boolean isActivityBackedBySafeActivity(ComponentName activityName) {
193 if (!mEnableActivityBlocking || !mDrivingStateListener.isRestricted()) {
194 return true;
195 }
196 StackInfo info = mSystemActivityMonitoringService.getFocusedStackForTopActivity(
197 activityName);
198 if (info == null) { // not top in focused stack
199 return true;
200 }
201 if (info.taskNames.length <= 1) { // nothing below this.
202 return false;
203 }
204 ComponentName activityBehind = ComponentName.unflattenFromString(
205 info.taskNames[info.taskNames.length - 2]);
206 return isActivityAllowedWhileDriving(activityBehind.getPackageName(),
207 activityBehind.getClassName());
208 }
209
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800210 public Looper getLooper() {
211 return mHandlerThread.getLooper();
212 }
213
214 private void assertPackageAndClassName(String packageName, String className) {
215 if (packageName == null) {
216 throw new IllegalArgumentException("Package name null");
217 }
218 if (className == null) {
219 throw new IllegalArgumentException("Class name null");
220 }
221 }
222
223 private AppBlockingPackageInfo searchFromBlacklistsLocked(String packageName) {
224 for (ClientPolicy policy : mClientPolicies.values()) {
225 AppBlockingPackageInfoWrapper wrapper = policy.blacklistsMap.get(packageName);
226 if (wrapper != null && wrapper.isMatching) {
227 return wrapper.info;
228 }
229 }
230 return null;
231 }
232
233 private AppBlockingPackageInfo searchFromWhitelistsLocked(String packageName) {
234 for (ClientPolicy policy : mClientPolicies.values()) {
235 AppBlockingPackageInfoWrapper wrapper = policy.whitelistsMap.get(packageName);
236 if (wrapper != null && wrapper.isMatching) {
237 return wrapper.info;
238 }
239 }
240 AppBlockingPackageInfoWrapper wrapper = mSystemWhitelists.get(packageName);
241 return (wrapper != null) ? wrapper.info : null;
242 }
243
244 private boolean isActivityInWhitelistsLocked(String packageName, String className) {
245 for (ClientPolicy policy : mClientPolicies.values()) {
246 if (isActivityInMapAndMatching(policy.whitelistsMap, packageName, className)) {
247 return true;
248 }
249 }
250 return isActivityInMapAndMatching(mSystemWhitelists, packageName, className);
251 }
252
253 private boolean isActivityInMapAndMatching(HashMap<String, AppBlockingPackageInfoWrapper> map,
254 String packageName, String className) {
255 AppBlockingPackageInfoWrapper wrapper = map.get(packageName);
256 if (wrapper == null || !wrapper.isMatching) {
257 return false;
258 }
259 return wrapper.info.isActivityCovered(className);
260 }
261
262 @Override
263 public void init() {
Keun-young Park98960812016-10-04 12:50:54 -0700264 if (!mEnableActivityBlocking) {
265 return;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800266 }
Keun-young Park98960812016-10-04 12:50:54 -0700267 synchronized (this) {
268 mHandler.requestInit();
Keun-young Park4727da32016-05-31 10:00:51 -0700269 }
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800270 }
271
272 @Override
273 public void release() {
Keun-young Park98960812016-10-04 12:50:54 -0700274 if (!mEnableActivityBlocking) {
275 return;
276 }
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800277 synchronized (this) {
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800278 mHandler.requestRelease();
Keun-young Park6dcc50b2016-10-10 19:01:11 -0700279 // wait for release do be done. This guarantees that init is done.
280 try {
281 wait();
282 } catch (InterruptedException e) {
283 }
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800284 mSystemWhitelists.clear();
285 mClientPolicies.clear();
286 if (mProxies != null) {
287 for (AppBlockingPolicyProxy proxy : mProxies) {
288 proxy.disconnect();
289 }
290 mProxies.clear();
291 }
292 wakeupClientsWaitingForPolicySetitngLocked();
293 }
Keun-young Park98960812016-10-04 12:50:54 -0700294 mSensorService.unregisterSensorListener(CarSensorManager.SENSOR_TYPE_DRIVING_STATUS,
295 mDrivingStateListener);
296 mSystemActivityMonitoringService.registerActivityLaunchListener(null);
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800297 }
298
299 // run from HandlerThread
300 private void doHandleInit() {
301 startAppBlockingPolicies();
302 generateSystemWhitelists();
Keun-young Park6dcc50b2016-10-10 19:01:11 -0700303 try {
304 mSensorService.registerOrUpdateSensorListener(
305 CarSensorManager.SENSOR_TYPE_DRIVING_STATUS, 0, mDrivingStateListener);
306 } catch (IllegalArgumentException e) {
307 // can happen while mocking is going on while init is still done.
308 Log.w(CarLog.TAG_PACKAGE, "sensor subscription failed", e);
309 return;
310 }
Keun-young Park98960812016-10-04 12:50:54 -0700311 mDrivingStateListener.resetState();
312 mSystemActivityMonitoringService.registerActivityLaunchListener(
313 mActivityLaunchListener);
314 blockTopActivitiesIfNecessary();
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800315 }
316
Keun-young Park6dcc50b2016-10-10 19:01:11 -0700317 private synchronized void doHandleRelease() {
318 notifyAll();
319 }
320
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800321 private void wakeupClientsWaitingForPolicySetitngLocked() {
322 for (CarAppBlockingPolicy waitingPolicy : mWaitingPolicies) {
323 synchronized (waitingPolicy) {
324 waitingPolicy.notifyAll();
325 }
326 }
327 mWaitingPolicies.clear();
328 }
329
330 private void doSetPolicy() {
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800331 synchronized (this) {
332 wakeupClientsWaitingForPolicySetitngLocked();
333 }
Keun-young Park4727da32016-05-31 10:00:51 -0700334 blockTopActivitiesIfNecessary();
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800335 }
336
337 private void doUpdatePolicy(String packageName, CarAppBlockingPolicy policy, int flags) {
338 if (DBG_POLICY_SET) {
339 Log.i(CarLog.TAG_PACKAGE, "setting policy from:" + packageName + ",policy:" + policy +
340 ",flags:0x" + Integer.toHexString(flags));
341 }
342 AppBlockingPackageInfoWrapper[] blacklistWrapper = verifyList(policy.blacklists);
343 AppBlockingPackageInfoWrapper[] whitelistWrapper = verifyList(policy.whitelists);
344 synchronized (this) {
345 ClientPolicy clientPolicy = mClientPolicies.get(packageName);
346 if (clientPolicy == null) {
347 clientPolicy = new ClientPolicy();
348 mClientPolicies.put(packageName, clientPolicy);
349 }
350 if ((flags & CarPackageManager.FLAG_SET_POLICY_ADD) != 0) {
351 clientPolicy.addToBlacklists(blacklistWrapper);
352 clientPolicy.addToWhitelists(whitelistWrapper);
353 } else if ((flags & CarPackageManager.FLAG_SET_POLICY_REMOVE) != 0) {
354 clientPolicy.removeBlacklists(blacklistWrapper);
355 clientPolicy.removeWhitelists(whitelistWrapper);
356 } else { //replace.
357 clientPolicy.replaceBlacklists(blacklistWrapper);
358 clientPolicy.replaceWhitelists(whitelistWrapper);
359 }
360 if ((flags & CarPackageManager.FLAG_SET_POLICY_WAIT_FOR_CHANGE) != 0) {
361 mWaitingPolicies.add(policy);
362 }
363 if (DBG_POLICY_SET) {
364 Log.i(CarLog.TAG_PACKAGE, "policy set:" + dumpPoliciesLocked(false));
365 }
366 }
Keun-young Park4727da32016-05-31 10:00:51 -0700367 blockTopActivitiesIfNecessary();
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800368 }
369
370 private AppBlockingPackageInfoWrapper[] verifyList(AppBlockingPackageInfo[] list) {
371 if (list == null) {
372 return null;
373 }
374 LinkedList<AppBlockingPackageInfoWrapper> wrappers = new LinkedList<>();
375 for (int i = 0; i < list.length; i++) {
376 AppBlockingPackageInfo info = list[i];
377 if (info == null) {
378 continue;
379 }
380 boolean isMatching = isInstalledPackageMatching(info);
381 wrappers.add(new AppBlockingPackageInfoWrapper(info, isMatching));
382 }
383 return wrappers.toArray(new AppBlockingPackageInfoWrapper[wrappers.size()]);
384 }
385
386 boolean isInstalledPackageMatching(AppBlockingPackageInfo info) {
387 PackageInfo packageInfo = null;
388 try {
389 packageInfo = mPackageManager.getPackageInfo(info.packageName,
390 PackageManager.GET_SIGNATURES);
391 } catch (NameNotFoundException e) {
392 return false;
393 }
394 if (packageInfo == null) {
395 return false;
396 }
397 // if it is system app and client specified the flag, do not check signature
398 if ((info.flags & AppBlockingPackageInfo.FLAG_SYSTEM_APP) == 0 ||
399 (!packageInfo.applicationInfo.isSystemApp() &&
400 !packageInfo.applicationInfo.isUpdatedSystemApp())) {
401 Signature[] signatires = packageInfo.signatures;
402 if (!isAnySignatureMatching(signatires, info.signatures)) {
403 return false;
404 }
405 }
406 int version = packageInfo.versionCode;
407 if (info.minRevisionCode == 0) {
408 if (info.maxRevisionCode == 0) { // all versions
409 return true;
410 } else { // only max version matters
411 return info.maxRevisionCode > version;
412 }
413 } else { // min version matters
414 if (info.maxRevisionCode == 0) {
415 return info.minRevisionCode < version;
416 } else {
417 return (info.minRevisionCode < version) && (info.maxRevisionCode > version);
418 }
419 }
420 }
421
422 /**
423 * Any signature from policy matching with package's signatures is treated as matching.
424 */
425 boolean isAnySignatureMatching(Signature[] fromPackage, Signature[] fromPolicy) {
426 if (fromPackage == null) {
427 return false;
428 }
429 if (fromPolicy == null) {
430 return false;
431 }
432 ArraySet<Signature> setFromPackage = new ArraySet<Signature>();
433 for (Signature sig : fromPackage) {
434 setFromPackage.add(sig);
435 }
436 for (Signature sig : fromPolicy) {
437 if (setFromPackage.contains(sig)) {
438 return true;
439 }
440 }
441 return false;
442 }
443
Keun-young Park4727da32016-05-31 10:00:51 -0700444 /**
445 * Return list of whitelist including default activity. Key is package name while
446 * value is list of activities. If list is empty, whole activities in the package
447 * are whitelisted.
448 * @return
449 */
450 private HashMap<String, Set<String>> parseConfigWhitelist() {
451 HashMap<String, Set<String>> packageToActivityMap = new HashMap<>();
452 Set<String> defaultActivity = new ArraySet<>();
453 defaultActivity.add(mActivityBlockingActivity.getClassName());
454 packageToActivityMap.put(mActivityBlockingActivity.getPackageName(), defaultActivity);
455 Resources res = mContext.getResources();
456 String whitelist = res.getString(R.string.defauiltActivityWhitelist);
Keun-young Park98960812016-10-04 12:50:54 -0700457 mDefauiltActivityWhitelist = whitelist;
Keun-young Park4727da32016-05-31 10:00:51 -0700458 String[] entries = whitelist.split(",");
459 for (String entry : entries) {
460 String[] packageActivityPair = entry.split("/");
461 Set<String> activities = packageToActivityMap.get(packageActivityPair[0]);
462 boolean newPackage = false;
463 if (activities == null) {
464 activities = new ArraySet<>();
465 newPackage = true;
466 packageToActivityMap.put(packageActivityPair[0], activities);
467 }
468 if (packageActivityPair.length == 1) { // whole package
469 activities.clear();
Keun-young Park98960812016-10-04 12:50:54 -0700470 } else if (packageActivityPair.length == 2) {
Keun-young Park4727da32016-05-31 10:00:51 -0700471 // add class name only when the whole package is not whitelisted.
472 if (newPackage || (activities.size() > 0)) {
473 activities.add(packageActivityPair[1]);
474 }
475 }
476 }
477 return packageToActivityMap;
478 }
479
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800480 private void generateSystemWhitelists() {
481 HashMap<String, AppBlockingPackageInfoWrapper> systemWhitelists = new HashMap<>();
Keun-young Park4727da32016-05-31 10:00:51 -0700482 HashMap<String, Set<String>> configWhitelist = parseConfigWhitelist();
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800483 // trust all system apps for services and trust all activities with car app meta-data.
484 List<PackageInfo> packages = mPackageManager.getInstalledPackages(0);
485 for (PackageInfo info : packages) {
486 if (info.applicationInfo != null && (info.applicationInfo.isSystemApp() ||
487 info.applicationInfo.isUpdatedSystemApp())) {
Keun-young Parkbdbce662016-01-19 18:35:30 -0800488 int flags = AppBlockingPackageInfo.FLAG_SYSTEM_APP;
Keun-young Park4727da32016-05-31 10:00:51 -0700489 Set<String> configActivitiesForPackage =
490 configWhitelist.get(info.packageName);
491 if (configActivitiesForPackage != null) {
492 if(configActivitiesForPackage.size() == 0) {
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800493 flags |= AppBlockingPackageInfo.FLAG_WHOLE_ACTIVITY;
Keun-young Park4727da32016-05-31 10:00:51 -0700494 }
495 } else {
496 configActivitiesForPackage = new ArraySet<>();
497 }
498 String[] activities = null;
Keun-young Park98960812016-10-04 12:50:54 -0700499 // Go through meta data if whole activities are not allowed already
Keun-young Park4727da32016-05-31 10:00:51 -0700500 if ((flags & AppBlockingPackageInfo.FLAG_WHOLE_ACTIVITY) == 0) {
501 CarAppMetadataInfo metadataInfo = CarAppMetadataReader.parseMetadata(mContext,
502 info.packageName);
503 if (metadataInfo != null) {
504 if (metadataInfo.useAllActivities) {
505 flags |= AppBlockingPackageInfo.FLAG_WHOLE_ACTIVITY;
506 } else if(metadataInfo.activities != null) {
507 for (String activity : metadataInfo.activities) {
508 configActivitiesForPackage.add(activity);
509 }
510 }
511 }
512 if (configActivitiesForPackage.size() > 0) {
513 activities = configActivitiesForPackage.toArray(
514 new String[configActivitiesForPackage.size()]);
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800515 }
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800516 }
Keun-young Parkbdbce662016-01-19 18:35:30 -0800517 AppBlockingPackageInfo appBlockingInfo = new AppBlockingPackageInfo(
518 info.packageName, 0, 0, flags, null, activities);
519 AppBlockingPackageInfoWrapper wrapper = new AppBlockingPackageInfoWrapper(
520 appBlockingInfo, true);
521 systemWhitelists.put(info.packageName, wrapper);
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800522 }
523 }
524 synchronized (this) {
525 mSystemWhitelists.putAll(systemWhitelists);
526 }
527 }
528
529 private void startAppBlockingPolicies() {
530 Intent policyIntent = new Intent();
531 policyIntent.setAction(CarAppBlockingPolicyService.SERVICE_INTERFACE);
532 List<ResolveInfo> policyInfos = mPackageManager.queryIntentServices(policyIntent, 0);
533 if (policyInfos == null) { //no need to wait for service binding and retrieval.
534 mHandler.requestPolicySetting();
535 return;
536 }
537 LinkedList<AppBlockingPolicyProxy> proxies = new LinkedList<>();
538 for (ResolveInfo resolveInfo : policyInfos) {
539 ServiceInfo serviceInfo = resolveInfo.serviceInfo;
540 if (serviceInfo == null) {
541 continue;
542 }
543 if (serviceInfo.isEnabled()) {
544 if (mPackageManager.checkPermission(Car.PERMISSION_CONTROL_APP_BLOCKING,
545 serviceInfo.packageName) != PackageManager.PERMISSION_GRANTED) {
546 continue;
547 }
548 Log.i(CarLog.TAG_PACKAGE, "found policy holding service:" + serviceInfo);
549 AppBlockingPolicyProxy proxy = new AppBlockingPolicyProxy(this, mContext,
550 serviceInfo);
551 proxy.connect();
552 proxies.add(proxy);
553 }
554 }
555 synchronized (this) {
556 mProxies = proxies;
557 }
558 }
559
560 public void onPolicyConnectionAndSet(AppBlockingPolicyProxy proxy,
561 CarAppBlockingPolicy policy) {
562 doHandlePolicyConnection(proxy, policy);
563 }
564
565 public void onPolicyConnectionFailure(AppBlockingPolicyProxy proxy) {
566 doHandlePolicyConnection(proxy, null);
567 }
568
569 private void doHandlePolicyConnection(AppBlockingPolicyProxy proxy,
570 CarAppBlockingPolicy policy) {
571 boolean shouldSetPolicy = false;
572 synchronized (this) {
573 if (mProxies == null) {
574 proxy.disconnect();
575 return;
576 }
577 mProxies.remove(proxy);
578 if (mProxies.size() == 0) {
579 shouldSetPolicy = true;
580 mProxies = null;
581 }
582 }
583 try {
584 if (policy != null) {
585 if (DBG_POLICY_SET) {
586 Log.i(CarLog.TAG_PACKAGE, "policy setting from policy service:" +
587 proxy.getPackageName());
588 }
589 doSetAppBlockingPolicy(proxy.getPackageName(), policy, 0, false /*setNow*/);
590 }
591 } finally {
592 proxy.disconnect();
593 if (shouldSetPolicy) {
594 mHandler.requestPolicySetting();
595 }
596 }
597 }
598
599 @Override
600 public void dump(PrintWriter writer) {
601 synchronized (this) {
602 writer.println("*PackageManagementService*");
Keun-young Park4727da32016-05-31 10:00:51 -0700603 writer.println("mEnableActivityBlocking:" + mEnableActivityBlocking);
604 writer.println("ActivityRestricted:" + mDrivingStateListener.isRestricted());
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800605 writer.print(dumpPoliciesLocked(true));
606 }
607 }
608
609 private String dumpPoliciesLocked(boolean dumpAll) {
610 StringBuilder sb = new StringBuilder();
611 if (dumpAll) {
612 sb.append("**System white list**\n");
613 for (AppBlockingPackageInfoWrapper wrapper : mSystemWhitelists.values()) {
614 sb.append(wrapper.toString() + "\n");
615 }
616 }
617 sb.append("**Client Policies**\n");
618 for (Entry<String, ClientPolicy> entry : mClientPolicies.entrySet()) {
619 sb.append("Client:" + entry.getKey() + "\n");
620 sb.append(" whitelists:\n");
621 for (AppBlockingPackageInfoWrapper wrapper : entry.getValue().whitelistsMap.values()) {
622 sb.append(wrapper.toString() + "\n");
623 }
624 sb.append(" blacklists:\n");
625 for (AppBlockingPackageInfoWrapper wrapper : entry.getValue().blacklistsMap.values()) {
626 sb.append(wrapper.toString() + "\n");
627 }
628 }
629 sb.append("**Unprocessed policy services**\n");
630 if (mProxies != null) {
631 for (AppBlockingPolicyProxy proxy : mProxies) {
632 sb.append(proxy.toString() + "\n");
633 }
634 }
Keun-young Park98960812016-10-04 12:50:54 -0700635 sb.append("**Default Whitelist string**\n");
636 sb.append(mDefauiltActivityWhitelist + "\n");
637
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800638 return sb.toString();
639 }
640
Keun-young Park4727da32016-05-31 10:00:51 -0700641 private void blockTopActivityIfNecessary(TopTaskInfoContainer topTask) {
642 boolean restricted = mDrivingStateListener.isRestricted();
643 if (!restricted) {
644 return;
645 }
646 doBlockTopActivityIfNotAllowed(topTask);
647 }
648
649 private void doBlockTopActivityIfNotAllowed(TopTaskInfoContainer topTask) {
650 boolean allowed = isActivityAllowedWhileDriving(
651 topTask.topActivity.getPackageName(),
652 topTask.topActivity.getClassName());
653 if (DBG_POLICY_ENFORCEMENT) {
654 Log.i(CarLog.TAG_PACKAGE, "new activity:" + topTask.toString() + " allowed:" + allowed);
655 }
656 if (!allowed) {
657 Log.i(CarLog.TAG_PACKAGE, "Current activity " + topTask.topActivity +
658 " not allowed, will block, number of tasks in stack:" +
659 topTask.stackInfo.taskIds.length);
660 Intent newActivityIntent = new Intent();
661 newActivityIntent.setComponent(mActivityBlockingActivity);
662 newActivityIntent.putExtra(
663 ActivityBlockingActivity.INTENT_KEY_BLOCKED_ACTIVITY,
664 topTask.topActivity.flattenToString());
665 mSystemActivityMonitoringService.blockActivity(topTask, newActivityIntent);
666 }
667 }
668
669 private void blockTopActivitiesIfNecessary() {
670 boolean restricted = mDrivingStateListener.isRestricted();
671 if (!restricted) {
672 return;
673 }
674 List<TopTaskInfoContainer> topTasks = mSystemActivityMonitoringService.getTopTasks();
675 for (TopTaskInfoContainer topTask : topTasks) {
676 doBlockTopActivityIfNotAllowed(topTask);
677 }
678 }
679
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800680 /**
681 * Reading policy and setting policy can take time. Run it in a separate handler thread.
682 */
683 private class PackageHandler extends Handler {
684 private final int MSG_INIT = 0;
685 private final int MSG_SET_POLICY = 1;
686 private final int MSG_UPDATE_POLICY = 2;
Keun-young Park6dcc50b2016-10-10 19:01:11 -0700687 private final int MSG_RELEASE = 3;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800688
689 private PackageHandler(Looper looper) {
690 super(looper);
691 }
692
693 private void requestInit() {
694 Message msg = obtainMessage(MSG_INIT);
695 sendMessage(msg);
696 }
697
698 private void requestRelease() {
699 removeMessages(MSG_INIT);
700 removeMessages(MSG_SET_POLICY);
701 removeMessages(MSG_UPDATE_POLICY);
Keun-young Park6dcc50b2016-10-10 19:01:11 -0700702 Message msg = obtainMessage(MSG_RELEASE);
703 sendMessage(msg);
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800704 }
705
706 private void requestPolicySetting() {
707 Message msg = obtainMessage(MSG_SET_POLICY);
708 sendMessage(msg);
709 }
710
711 private void requestUpdatingPolicy(String packageName, CarAppBlockingPolicy policy,
712 int flags) {
713 Pair<String, CarAppBlockingPolicy> pair = new Pair<>(packageName, policy);
714 Message msg = obtainMessage(MSG_UPDATE_POLICY, flags, 0, pair);
715 sendMessage(msg);
716 }
717
718 @Override
719 public void handleMessage(Message msg) {
720 switch (msg.what) {
721 case MSG_INIT:
722 doHandleInit();
723 break;
724 case MSG_SET_POLICY:
725 doSetPolicy();
726 break;
727 case MSG_UPDATE_POLICY:
728 Pair<String, CarAppBlockingPolicy> pair =
729 (Pair<String, CarAppBlockingPolicy>) msg.obj;
730 doUpdatePolicy(pair.first, pair.second, msg.arg1);
731 break;
Keun-young Park6dcc50b2016-10-10 19:01:11 -0700732 case MSG_RELEASE:
733 doHandleRelease();
734 break;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800735 }
736 }
737 }
738
739 private static class AppBlockingPackageInfoWrapper {
740 private final AppBlockingPackageInfo info;
741 /**
742 * Whether the current info is matching with the target package in system. Mismatch can
743 * happen for version out of range or signature mismatch.
744 */
745 private boolean isMatching;
746
747 private AppBlockingPackageInfoWrapper(AppBlockingPackageInfo info, boolean isMatching) {
748 this.info =info;
749 this.isMatching = isMatching;
750 }
751
752 @Override
753 public String toString() {
754 return "AppBlockingPackageInfoWrapper [info=" + info + ", isMatching=" + isMatching +
755 "]";
756 }
757 }
758
759 /**
760 * Client policy holder per each client. Should be accessed with CarpackageManagerService.this
761 * held.
762 */
763 private static class ClientPolicy {
764 private final HashMap<String, AppBlockingPackageInfoWrapper> whitelistsMap =
765 new HashMap<>();
766 private final HashMap<String, AppBlockingPackageInfoWrapper> blacklistsMap =
767 new HashMap<>();
768
769 private void replaceWhitelists(AppBlockingPackageInfoWrapper[] whitelists) {
770 whitelistsMap.clear();
771 addToWhitelists(whitelists);
772 }
773
774 private void addToWhitelists(AppBlockingPackageInfoWrapper[] whitelists) {
775 if (whitelists == null) {
776 return;
777 }
778 for (AppBlockingPackageInfoWrapper wrapper : whitelists) {
779 if (wrapper != null) {
780 whitelistsMap.put(wrapper.info.packageName, wrapper);
781 }
782 }
783 }
784
785 private void removeWhitelists(AppBlockingPackageInfoWrapper[] whitelists) {
786 if (whitelists == null) {
787 return;
788 }
789 for (AppBlockingPackageInfoWrapper wrapper : whitelists) {
790 if (wrapper != null) {
791 whitelistsMap.remove(wrapper.info.packageName);
792 }
793 }
794 }
795
796 private void replaceBlacklists(AppBlockingPackageInfoWrapper[] blacklists) {
797 blacklistsMap.clear();
798 addToBlacklists(blacklists);
799 }
800
801 private void addToBlacklists(AppBlockingPackageInfoWrapper[] blacklists) {
802 if (blacklists == null) {
803 return;
804 }
805 for (AppBlockingPackageInfoWrapper wrapper : blacklists) {
806 if (wrapper != null) {
807 blacklistsMap.put(wrapper.info.packageName, wrapper);
808 }
809 }
810 }
811
812 private void removeBlacklists(AppBlockingPackageInfoWrapper[] blacklists) {
813 if (blacklists == null) {
814 return;
815 }
816 for (AppBlockingPackageInfoWrapper wrapper : blacklists) {
817 if (wrapper != null) {
818 blacklistsMap.remove(wrapper.info.packageName);
819 }
820 }
821 }
822 }
Keun-young Park4727da32016-05-31 10:00:51 -0700823
824 private class ActivityLaunchListener
825 implements SystemActivityMonitoringService.ActivityLaunchListener {
826 @Override
827 public void onActivityLaunch(TopTaskInfoContainer topTask) {
828 blockTopActivityIfNecessary(topTask);
829 }
830 }
831
832 private class SensorListener extends ICarSensorEventListener.Stub {
833 private int mLatestDrivingState;
834
835 private void resetState() {
836 CarSensorEvent lastEvent = mSensorService.getLatestSensorEvent(
837 CarSensorManager.SENSOR_TYPE_DRIVING_STATUS);
838 boolean shouldBlock = false;
839 synchronized (this) {
840 if (lastEvent == null) {
841 // When driving status is not available yet, do not block.
842 // This happens during bootup.
843 mLatestDrivingState = CarSensorEvent.DRIVE_STATUS_UNRESTRICTED;
844 } else {
845 mLatestDrivingState = lastEvent.intValues[0];
846 }
847 if (mLatestDrivingState != CarSensorEvent.DRIVE_STATUS_UNRESTRICTED) {
848 shouldBlock = true;
849 }
850 }
851 if (shouldBlock) {
852 blockTopActivitiesIfNecessary();
853 }
854 }
855
856 private synchronized boolean isRestricted() {
857 return mLatestDrivingState != CarSensorEvent.DRIVE_STATUS_UNRESTRICTED;
858 }
859
860 @Override
861 public void onSensorChanged(List<CarSensorEvent> events) {
862 resetState();
863 }
864 }
Keun-young Park4aeb4bf2015-12-08 18:31:33 -0800865}