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