1 /* 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 */ 16 package com.android.car.pm; 17 18 import android.app.ActivityManager.StackInfo; 19 import android.car.Car; 20 import android.car.content.pm.AppBlockingPackageInfo; 21 import android.car.content.pm.CarAppBlockingPolicy; 22 import android.car.content.pm.CarAppBlockingPolicyService; 23 import android.car.content.pm.CarPackageManager; 24 import android.car.content.pm.ICarPackageManager; 25 import android.car.hardware.CarSensorEvent; 26 import android.car.hardware.CarSensorManager; 27 import android.car.hardware.ICarSensorEventListener; 28 import android.content.ComponentName; 29 import android.content.Context; 30 import android.content.Intent; 31 import android.content.pm.PackageInfo; 32 import android.content.pm.PackageManager; 33 import android.content.pm.PackageManager.NameNotFoundException; 34 import android.content.pm.ResolveInfo; 35 import android.content.pm.ServiceInfo; 36 import android.content.pm.Signature; 37 import android.content.res.Resources; 38 import android.os.Handler; 39 import android.os.HandlerThread; 40 import android.os.Looper; 41 import android.os.Message; 42 import android.util.ArraySet; 43 import android.util.Log; 44 import android.util.Pair; 45 46 import com.android.car.CarLog; 47 import com.android.car.CarSensorService; 48 import com.android.car.CarServiceBase; 49 import com.android.car.CarServiceUtils; 50 import com.android.car.R; 51 import com.android.car.SystemActivityMonitoringService; 52 import com.android.car.SystemActivityMonitoringService.TopTaskInfoContainer; 53 import com.android.car.pm.CarAppMetadataReader.CarAppMetadataInfo; 54 import com.android.internal.annotations.GuardedBy; 55 56 import java.io.PrintWriter; 57 import java.util.HashMap; 58 import java.util.LinkedList; 59 import java.util.List; 60 import java.util.Map.Entry; 61 import java.util.Set; 62 63 //TODO monitor app installing and refresh policy, bug: 31970400 64 65 public class CarPackageManagerService extends ICarPackageManager.Stub implements CarServiceBase { 66 static final boolean DBG_POLICY_SET = false; 67 static final boolean DBG_POLICY_CHECK = false; 68 static final boolean DBG_POLICY_ENFORCEMENT = false; 69 70 private final Context mContext; 71 private final SystemActivityMonitoringService mSystemActivityMonitoringService; 72 private final CarSensorService mSensorService; 73 private final PackageManager mPackageManager; 74 75 private final HandlerThread mHandlerThread; 76 private final PackageHandler mHandler; 77 78 private String mDefauiltActivityWhitelist; 79 /** 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; 90 91 @GuardedBy("this") 92 private final LinkedList<CarAppBlockingPolicy> mWaitingPolicies = new LinkedList<>(); 93 94 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) { 102 mContext = context; 103 mSensorService = sensorService; 104 mSystemActivityMonitoringService = systemActivityMonitoringService; 105 mPackageManager = mContext.getPackageManager(); 106 mHandlerThread = new HandlerThread(CarLog.TAG_PACKAGE); 107 mHandlerThread.start(); 108 mHandler = new PackageHandler(mHandlerThread.getLooper()); 109 Resources res = context.getResources(); 110 mEnableActivityBlocking = res.getBoolean(R.bool.enableActivityBlockingForSafety); 111 String blockingActivity = res.getString(R.string.activityBlockingActivity); 112 mActivityBlockingActivity = ComponentName.unflattenFromString(blockingActivity); 113 } 114 115 @Override 116 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.assertPackageName(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 191 @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 210 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() { 264 if (!mEnableActivityBlocking) { 265 return; 266 } 267 synchronized (this) { 268 mHandler.requestInit(); 269 } 270 } 271 272 @Override 273 public void release() { 274 if (!mEnableActivityBlocking) { 275 return; 276 } 277 synchronized (this) { 278 mHandler.requestRelease(); 279 // wait for release do be done. This guarantees that init is done. 280 try { 281 wait(); 282 } catch (InterruptedException e) { 283 } 284 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 } 294 mSensorService.unregisterSensorListener(CarSensorManager.SENSOR_TYPE_DRIVING_STATUS, 295 mDrivingStateListener); 296 mSystemActivityMonitoringService.registerActivityLaunchListener(null); 297 } 298 299 // run from HandlerThread 300 private void doHandleInit() { 301 startAppBlockingPolicies(); 302 generateSystemWhitelists(); 303 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 } 311 mDrivingStateListener.resetState(); 312 mSystemActivityMonitoringService.registerActivityLaunchListener( 313 mActivityLaunchListener); 314 blockTopActivitiesIfNecessary(); 315 } 316 317 private synchronized void doHandleRelease() { 318 notifyAll(); 319 } 320 321 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() { 331 synchronized (this) { 332 wakeupClientsWaitingForPolicySetitngLocked(); 333 } 334 blockTopActivitiesIfNecessary(); 335 } 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 } 367 blockTopActivitiesIfNecessary(); 368 } 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 444 /** 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); 457 mDefauiltActivityWhitelist = whitelist; 458 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(); 470 } else if (packageActivityPair.length == 2) { 471 // 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 480 private void generateSystemWhitelists() { 481 HashMap<String, AppBlockingPackageInfoWrapper> systemWhitelists = new HashMap<>(); 482 HashMap<String, Set<String>> configWhitelist = parseConfigWhitelist(); 483 // 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())) { 488 int flags = AppBlockingPackageInfo.FLAG_SYSTEM_APP; 489 Set<String> configActivitiesForPackage = 490 configWhitelist.get(info.packageName); 491 if (configActivitiesForPackage != null) { 492 if(configActivitiesForPackage.size() == 0) { 493 flags |= AppBlockingPackageInfo.FLAG_WHOLE_ACTIVITY; 494 } 495 } else { 496 configActivitiesForPackage = new ArraySet<>(); 497 } 498 String[] activities = null; 499 // Go through meta data if whole activities are not allowed already 500 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()]); 515 } 516 } 517 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); 522 } 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*"); 603 writer.println("mEnableActivityBlocking:" + mEnableActivityBlocking); 604 writer.println("ActivityRestricted:" + mDrivingStateListener.isRestricted()); 605 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 } 635 sb.append("**Default Whitelist string**\n"); 636 sb.append(mDefauiltActivityWhitelist + "\n"); 637 638 return sb.toString(); 639 } 640 641 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 680 /** 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; 687 private final int MSG_RELEASE = 3; 688 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); 702 Message msg = obtainMessage(MSG_RELEASE); 703 sendMessage(msg); 704 } 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; 732 case MSG_RELEASE: 733 doHandleRelease(); 734 break; 735 } 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 } 823 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 } 865 } 866