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.car.Car; 19 import android.car.content.pm.AppBlockingPackageInfo; 20 import android.car.content.pm.CarAppBlockingPolicy; 21 import android.car.content.pm.CarAppBlockingPolicyService; 22 import android.car.content.pm.CarPackageManager; 23 import android.car.content.pm.ICarPackageManager; 24 import android.content.Context; 25 import android.content.Intent; 26 import android.content.pm.PackageInfo; 27 import android.content.pm.PackageManager; 28 import android.content.pm.PackageManager.NameNotFoundException; 29 import android.content.pm.ServiceInfo; 30 import android.content.pm.ResolveInfo; 31 import android.content.pm.Signature; 32 import android.os.Handler; 33 import android.os.HandlerThread; 34 import android.os.Looper; 35 import android.os.Message; 36 import android.util.ArraySet; 37 import android.util.Log; 38 import android.util.Pair; 39 40 import com.android.car.CarLog; 41 import com.android.car.CarServiceBase; 42 import com.android.car.CarServiceUtils; 43 import com.android.car.pm.CarAppMetadataReader.CarAppMetadataInfo; 44 import com.android.internal.annotations.GuardedBy; 45 46 import java.io.PrintWriter; 47 import java.util.Arrays; 48 import java.util.HashMap; 49 import java.util.LinkedList; 50 import java.util.List; 51 import java.util.Map.Entry; 52 53 //TODO monitor app installing and refresh policy 54 55 public class CarPackageManagerService extends ICarPackageManager.Stub implements CarServiceBase { 56 static final boolean DBG_POLICY_SET = true; 57 static final boolean DBG_POLICY_CHECK = false; 58 59 private final Context mContext; 60 private final PackageManager mPackageManager; 61 62 private final HandlerThread mHandlerThread; 63 private final PackageHandler mHandler; 64 65 /** 66 * Hold policy set from policy service or client. 67 * Key: packageName of policy service 68 */ 69 @GuardedBy("this") 70 private final HashMap<String, ClientPolicy> mClientPolicies = 71 new HashMap<>(); 72 @GuardedBy("this") 73 private HashMap<String, AppBlockingPackageInfoWrapper> mSystemWhitelists = new HashMap<>(); 74 @GuardedBy("this") 75 private LinkedList<AppBlockingPolicyProxy> mProxies; 76 @GuardedBy("this") 77 private boolean mReleased = true; 78 79 @GuardedBy("this") 80 private final LinkedList<CarAppBlockingPolicy> mWaitingPolicies = new LinkedList<>(); 81 CarPackageManagerService(Context context)82 public CarPackageManagerService(Context context) { 83 mContext = context; 84 mPackageManager = mContext.getPackageManager(); 85 mHandlerThread = new HandlerThread(CarLog.TAG_PACKAGE); 86 mHandlerThread.start(); 87 mHandler = new PackageHandler(mHandlerThread.getLooper()); 88 } 89 90 @Override setAppBlockingPolicy(String packageName, CarAppBlockingPolicy policy, int flags)91 public void setAppBlockingPolicy(String packageName, CarAppBlockingPolicy policy, int flags) { 92 if (DBG_POLICY_SET) { 93 Log.i(CarLog.TAG_PACKAGE, "policy setting from binder call, client:" + packageName); 94 } 95 doSetAppBlockingPolicy(packageName, policy, flags, true /*setNow*/); 96 } 97 doSetAppBlockingPolicy(String packageName, CarAppBlockingPolicy policy, int flags, boolean setNow)98 private void doSetAppBlockingPolicy(String packageName, CarAppBlockingPolicy policy, int flags, 99 boolean setNow) { 100 if (mContext.checkCallingOrSelfPermission(Car.PERMISSION_CONTROL_APP_BLOCKING) 101 != PackageManager.PERMISSION_GRANTED) { 102 throw new SecurityException( 103 "requires permission " + Car.PERMISSION_CONTROL_APP_BLOCKING); 104 } 105 CarServiceUtils.assertPakcageName(mContext, packageName); 106 if (policy == null) { 107 throw new IllegalArgumentException("policy cannot be null"); 108 } 109 if ((flags & CarPackageManager.FLAG_SET_POLICY_ADD) != 0 && 110 (flags & CarPackageManager.FLAG_SET_POLICY_REMOVE) != 0) { 111 throw new IllegalArgumentException( 112 "Cannot set both FLAG_SET_POLICY_ADD and FLAG_SET_POLICY_REMOVE flag"); 113 } 114 mHandler.requestUpdatingPolicy(packageName, policy, flags); 115 if (setNow) { 116 mHandler.requestPolicySetting(); 117 if ((flags & CarPackageManager.FLAG_SET_POLICY_WAIT_FOR_CHANGE) != 0) { 118 synchronized (policy) { 119 try { 120 policy.wait(); 121 } catch (InterruptedException e) { 122 } 123 } 124 } 125 } 126 } 127 128 @Override isActivityAllowedWhileDriving(String packageName, String className)129 public boolean isActivityAllowedWhileDriving(String packageName, String className) { 130 assertPackageAndClassName(packageName, className); 131 synchronized (this) { 132 if (DBG_POLICY_CHECK) { 133 Log.i(CarLog.TAG_PACKAGE, "isActivityAllowedWhileDriving" + 134 dumpPoliciesLocked(false)); 135 } 136 AppBlockingPackageInfo info = searchFromBlacklistsLocked(packageName); 137 if (info != null) { 138 return false; 139 } 140 return isActivityInWhitelistsLocked(packageName, className); 141 } 142 } 143 144 @Override isServiceAllowedWhileDriving(String packageName, String className)145 public boolean isServiceAllowedWhileDriving(String packageName, String className) { 146 if (packageName == null) { 147 throw new IllegalArgumentException("Package name null"); 148 } 149 synchronized (this) { 150 if (DBG_POLICY_CHECK) { 151 Log.i(CarLog.TAG_PACKAGE, "isServiceAllowedWhileDriving" + 152 dumpPoliciesLocked(false)); 153 } 154 AppBlockingPackageInfo info = searchFromBlacklistsLocked(packageName); 155 if (info != null) { 156 return false; 157 } 158 info = searchFromWhitelistsLocked(packageName); 159 if (info != null) { 160 return true; 161 } 162 } 163 return false; 164 } 165 getLooper()166 public Looper getLooper() { 167 return mHandlerThread.getLooper(); 168 } 169 assertPackageAndClassName(String packageName, String className)170 private void assertPackageAndClassName(String packageName, String className) { 171 if (packageName == null) { 172 throw new IllegalArgumentException("Package name null"); 173 } 174 if (className == null) { 175 throw new IllegalArgumentException("Class name null"); 176 } 177 } 178 searchFromBlacklistsLocked(String packageName)179 private AppBlockingPackageInfo searchFromBlacklistsLocked(String packageName) { 180 for (ClientPolicy policy : mClientPolicies.values()) { 181 AppBlockingPackageInfoWrapper wrapper = policy.blacklistsMap.get(packageName); 182 if (wrapper != null && wrapper.isMatching) { 183 return wrapper.info; 184 } 185 } 186 return null; 187 } 188 searchFromWhitelistsLocked(String packageName)189 private AppBlockingPackageInfo searchFromWhitelistsLocked(String packageName) { 190 for (ClientPolicy policy : mClientPolicies.values()) { 191 AppBlockingPackageInfoWrapper wrapper = policy.whitelistsMap.get(packageName); 192 if (wrapper != null && wrapper.isMatching) { 193 return wrapper.info; 194 } 195 } 196 AppBlockingPackageInfoWrapper wrapper = mSystemWhitelists.get(packageName); 197 return (wrapper != null) ? wrapper.info : null; 198 } 199 isActivityInWhitelistsLocked(String packageName, String className)200 private boolean isActivityInWhitelistsLocked(String packageName, String className) { 201 for (ClientPolicy policy : mClientPolicies.values()) { 202 if (isActivityInMapAndMatching(policy.whitelistsMap, packageName, className)) { 203 return true; 204 } 205 } 206 return isActivityInMapAndMatching(mSystemWhitelists, packageName, className); 207 } 208 isActivityInMapAndMatching(HashMap<String, AppBlockingPackageInfoWrapper> map, String packageName, String className)209 private boolean isActivityInMapAndMatching(HashMap<String, AppBlockingPackageInfoWrapper> map, 210 String packageName, String className) { 211 AppBlockingPackageInfoWrapper wrapper = map.get(packageName); 212 if (wrapper == null || !wrapper.isMatching) { 213 return false; 214 } 215 return wrapper.info.isActivityCovered(className); 216 } 217 218 @Override init()219 public void init() { 220 synchronized (this) { 221 mReleased = false; 222 mHandler.requestInit(); 223 } 224 } 225 226 @Override release()227 public void release() { 228 synchronized (this) { 229 mReleased = true; 230 mHandler.requestRelease(); 231 mSystemWhitelists.clear(); 232 mClientPolicies.clear(); 233 if (mProxies != null) { 234 for (AppBlockingPolicyProxy proxy : mProxies) { 235 proxy.disconnect(); 236 } 237 mProxies.clear(); 238 } 239 wakeupClientsWaitingForPolicySetitngLocked(); 240 } 241 } 242 243 // run from HandlerThread doHandleInit()244 private void doHandleInit() { 245 startAppBlockingPolicies(); 246 generateSystemWhitelists(); 247 } 248 wakeupClientsWaitingForPolicySetitngLocked()249 private void wakeupClientsWaitingForPolicySetitngLocked() { 250 for (CarAppBlockingPolicy waitingPolicy : mWaitingPolicies) { 251 synchronized (waitingPolicy) { 252 waitingPolicy.notifyAll(); 253 } 254 } 255 mWaitingPolicies.clear(); 256 } 257 doSetPolicy()258 private void doSetPolicy() { 259 //TODO should set policy to AMS 260 // waiting for framework API to be ready 261 synchronized (this) { 262 wakeupClientsWaitingForPolicySetitngLocked(); 263 } 264 } 265 doUpdatePolicy(String packageName, CarAppBlockingPolicy policy, int flags)266 private void doUpdatePolicy(String packageName, CarAppBlockingPolicy policy, int flags) { 267 if (DBG_POLICY_SET) { 268 Log.i(CarLog.TAG_PACKAGE, "setting policy from:" + packageName + ",policy:" + policy + 269 ",flags:0x" + Integer.toHexString(flags)); 270 } 271 AppBlockingPackageInfoWrapper[] blacklistWrapper = verifyList(policy.blacklists); 272 AppBlockingPackageInfoWrapper[] whitelistWrapper = verifyList(policy.whitelists); 273 synchronized (this) { 274 ClientPolicy clientPolicy = mClientPolicies.get(packageName); 275 if (clientPolicy == null) { 276 clientPolicy = new ClientPolicy(); 277 mClientPolicies.put(packageName, clientPolicy); 278 } 279 if ((flags & CarPackageManager.FLAG_SET_POLICY_ADD) != 0) { 280 clientPolicy.addToBlacklists(blacklistWrapper); 281 clientPolicy.addToWhitelists(whitelistWrapper); 282 } else if ((flags & CarPackageManager.FLAG_SET_POLICY_REMOVE) != 0) { 283 clientPolicy.removeBlacklists(blacklistWrapper); 284 clientPolicy.removeWhitelists(whitelistWrapper); 285 } else { //replace. 286 clientPolicy.replaceBlacklists(blacklistWrapper); 287 clientPolicy.replaceWhitelists(whitelistWrapper); 288 } 289 if ((flags & CarPackageManager.FLAG_SET_POLICY_WAIT_FOR_CHANGE) != 0) { 290 mWaitingPolicies.add(policy); 291 } 292 if (DBG_POLICY_SET) { 293 Log.i(CarLog.TAG_PACKAGE, "policy set:" + dumpPoliciesLocked(false)); 294 } 295 } 296 } 297 verifyList(AppBlockingPackageInfo[] list)298 private AppBlockingPackageInfoWrapper[] verifyList(AppBlockingPackageInfo[] list) { 299 if (list == null) { 300 return null; 301 } 302 LinkedList<AppBlockingPackageInfoWrapper> wrappers = new LinkedList<>(); 303 for (int i = 0; i < list.length; i++) { 304 AppBlockingPackageInfo info = list[i]; 305 if (info == null) { 306 continue; 307 } 308 boolean isMatching = isInstalledPackageMatching(info); 309 wrappers.add(new AppBlockingPackageInfoWrapper(info, isMatching)); 310 } 311 return wrappers.toArray(new AppBlockingPackageInfoWrapper[wrappers.size()]); 312 } 313 isInstalledPackageMatching(AppBlockingPackageInfo info)314 boolean isInstalledPackageMatching(AppBlockingPackageInfo info) { 315 PackageInfo packageInfo = null; 316 try { 317 packageInfo = mPackageManager.getPackageInfo(info.packageName, 318 PackageManager.GET_SIGNATURES); 319 } catch (NameNotFoundException e) { 320 return false; 321 } 322 if (packageInfo == null) { 323 return false; 324 } 325 // if it is system app and client specified the flag, do not check signature 326 if ((info.flags & AppBlockingPackageInfo.FLAG_SYSTEM_APP) == 0 || 327 (!packageInfo.applicationInfo.isSystemApp() && 328 !packageInfo.applicationInfo.isUpdatedSystemApp())) { 329 Signature[] signatires = packageInfo.signatures; 330 if (!isAnySignatureMatching(signatires, info.signatures)) { 331 return false; 332 } 333 } 334 int version = packageInfo.versionCode; 335 if (info.minRevisionCode == 0) { 336 if (info.maxRevisionCode == 0) { // all versions 337 return true; 338 } else { // only max version matters 339 return info.maxRevisionCode > version; 340 } 341 } else { // min version matters 342 if (info.maxRevisionCode == 0) { 343 return info.minRevisionCode < version; 344 } else { 345 return (info.minRevisionCode < version) && (info.maxRevisionCode > version); 346 } 347 } 348 } 349 350 /** 351 * Any signature from policy matching with package's signatures is treated as matching. 352 */ isAnySignatureMatching(Signature[] fromPackage, Signature[] fromPolicy)353 boolean isAnySignatureMatching(Signature[] fromPackage, Signature[] fromPolicy) { 354 if (fromPackage == null) { 355 return false; 356 } 357 if (fromPolicy == null) { 358 return false; 359 } 360 ArraySet<Signature> setFromPackage = new ArraySet<Signature>(); 361 for (Signature sig : fromPackage) { 362 setFromPackage.add(sig); 363 } 364 for (Signature sig : fromPolicy) { 365 if (setFromPackage.contains(sig)) { 366 return true; 367 } 368 } 369 return false; 370 } 371 generateSystemWhitelists()372 private void generateSystemWhitelists() { 373 HashMap<String, AppBlockingPackageInfoWrapper> systemWhitelists = new HashMap<>(); 374 // trust all system apps for services and trust all activities with car app meta-data. 375 List<PackageInfo> packages = mPackageManager.getInstalledPackages(0); 376 for (PackageInfo info : packages) { 377 if (info.applicationInfo != null && (info.applicationInfo.isSystemApp() || 378 info.applicationInfo.isUpdatedSystemApp())) { 379 CarAppMetadataInfo metadataInfo = CarAppMetadataReader.parseMetadata(mContext, 380 info.packageName); 381 int flags = AppBlockingPackageInfo.FLAG_SYSTEM_APP; 382 String[] activities = null; 383 if (metadataInfo != null) { 384 if (metadataInfo.useAllActivities) { 385 flags |= AppBlockingPackageInfo.FLAG_WHOLE_ACTIVITY; 386 } else { 387 activities = metadataInfo.activities; 388 } 389 } 390 AppBlockingPackageInfo appBlockingInfo = new AppBlockingPackageInfo( 391 info.packageName, 0, 0, flags, null, activities); 392 AppBlockingPackageInfoWrapper wrapper = new AppBlockingPackageInfoWrapper( 393 appBlockingInfo, true); 394 systemWhitelists.put(info.packageName, wrapper); 395 } 396 } 397 synchronized (this) { 398 mSystemWhitelists.putAll(systemWhitelists); 399 } 400 } 401 startAppBlockingPolicies()402 private void startAppBlockingPolicies() { 403 Intent policyIntent = new Intent(); 404 policyIntent.setAction(CarAppBlockingPolicyService.SERVICE_INTERFACE); 405 List<ResolveInfo> policyInfos = mPackageManager.queryIntentServices(policyIntent, 0); 406 if (policyInfos == null) { //no need to wait for service binding and retrieval. 407 mHandler.requestPolicySetting(); 408 return; 409 } 410 LinkedList<AppBlockingPolicyProxy> proxies = new LinkedList<>(); 411 for (ResolveInfo resolveInfo : policyInfos) { 412 ServiceInfo serviceInfo = resolveInfo.serviceInfo; 413 if (serviceInfo == null) { 414 continue; 415 } 416 if (serviceInfo.isEnabled()) { 417 if (mPackageManager.checkPermission(Car.PERMISSION_CONTROL_APP_BLOCKING, 418 serviceInfo.packageName) != PackageManager.PERMISSION_GRANTED) { 419 continue; 420 } 421 Log.i(CarLog.TAG_PACKAGE, "found policy holding service:" + serviceInfo); 422 AppBlockingPolicyProxy proxy = new AppBlockingPolicyProxy(this, mContext, 423 serviceInfo); 424 proxy.connect(); 425 proxies.add(proxy); 426 } 427 } 428 synchronized (this) { 429 mProxies = proxies; 430 } 431 } 432 onPolicyConnectionAndSet(AppBlockingPolicyProxy proxy, CarAppBlockingPolicy policy)433 public void onPolicyConnectionAndSet(AppBlockingPolicyProxy proxy, 434 CarAppBlockingPolicy policy) { 435 doHandlePolicyConnection(proxy, policy); 436 } 437 onPolicyConnectionFailure(AppBlockingPolicyProxy proxy)438 public void onPolicyConnectionFailure(AppBlockingPolicyProxy proxy) { 439 doHandlePolicyConnection(proxy, null); 440 } 441 doHandlePolicyConnection(AppBlockingPolicyProxy proxy, CarAppBlockingPolicy policy)442 private void doHandlePolicyConnection(AppBlockingPolicyProxy proxy, 443 CarAppBlockingPolicy policy) { 444 boolean shouldSetPolicy = false; 445 synchronized (this) { 446 if (mProxies == null) { 447 proxy.disconnect(); 448 return; 449 } 450 mProxies.remove(proxy); 451 if (mProxies.size() == 0) { 452 shouldSetPolicy = true; 453 mProxies = null; 454 } 455 } 456 try { 457 if (policy != null) { 458 if (DBG_POLICY_SET) { 459 Log.i(CarLog.TAG_PACKAGE, "policy setting from policy service:" + 460 proxy.getPackageName()); 461 } 462 doSetAppBlockingPolicy(proxy.getPackageName(), policy, 0, false /*setNow*/); 463 } 464 } finally { 465 proxy.disconnect(); 466 if (shouldSetPolicy) { 467 mHandler.requestPolicySetting(); 468 } 469 } 470 } 471 472 @Override dump(PrintWriter writer)473 public void dump(PrintWriter writer) { 474 synchronized (this) { 475 writer.println("*PackageManagementService*"); 476 writer.print(dumpPoliciesLocked(true)); 477 } 478 } 479 dumpPoliciesLocked(boolean dumpAll)480 private String dumpPoliciesLocked(boolean dumpAll) { 481 StringBuilder sb = new StringBuilder(); 482 if (dumpAll) { 483 sb.append("**System white list**\n"); 484 for (AppBlockingPackageInfoWrapper wrapper : mSystemWhitelists.values()) { 485 sb.append(wrapper.toString() + "\n"); 486 } 487 } 488 sb.append("**Client Policies**\n"); 489 for (Entry<String, ClientPolicy> entry : mClientPolicies.entrySet()) { 490 sb.append("Client:" + entry.getKey() + "\n"); 491 sb.append(" whitelists:\n"); 492 for (AppBlockingPackageInfoWrapper wrapper : entry.getValue().whitelistsMap.values()) { 493 sb.append(wrapper.toString() + "\n"); 494 } 495 sb.append(" blacklists:\n"); 496 for (AppBlockingPackageInfoWrapper wrapper : entry.getValue().blacklistsMap.values()) { 497 sb.append(wrapper.toString() + "\n"); 498 } 499 } 500 sb.append("**Unprocessed policy services**\n"); 501 if (mProxies != null) { 502 for (AppBlockingPolicyProxy proxy : mProxies) { 503 sb.append(proxy.toString() + "\n"); 504 } 505 } 506 return sb.toString(); 507 } 508 509 /** 510 * Reading policy and setting policy can take time. Run it in a separate handler thread. 511 */ 512 private class PackageHandler extends Handler { 513 private final int MSG_INIT = 0; 514 private final int MSG_SET_POLICY = 1; 515 private final int MSG_UPDATE_POLICY = 2; 516 PackageHandler(Looper looper)517 private PackageHandler(Looper looper) { 518 super(looper); 519 } 520 requestInit()521 private void requestInit() { 522 Message msg = obtainMessage(MSG_INIT); 523 sendMessage(msg); 524 } 525 requestRelease()526 private void requestRelease() { 527 removeMessages(MSG_INIT); 528 removeMessages(MSG_SET_POLICY); 529 removeMessages(MSG_UPDATE_POLICY); 530 } 531 requestPolicySetting()532 private void requestPolicySetting() { 533 Message msg = obtainMessage(MSG_SET_POLICY); 534 sendMessage(msg); 535 } 536 requestUpdatingPolicy(String packageName, CarAppBlockingPolicy policy, int flags)537 private void requestUpdatingPolicy(String packageName, CarAppBlockingPolicy policy, 538 int flags) { 539 Pair<String, CarAppBlockingPolicy> pair = new Pair<>(packageName, policy); 540 Message msg = obtainMessage(MSG_UPDATE_POLICY, flags, 0, pair); 541 sendMessage(msg); 542 } 543 544 @Override handleMessage(Message msg)545 public void handleMessage(Message msg) { 546 switch (msg.what) { 547 case MSG_INIT: 548 doHandleInit(); 549 break; 550 case MSG_SET_POLICY: 551 doSetPolicy(); 552 break; 553 case MSG_UPDATE_POLICY: 554 Pair<String, CarAppBlockingPolicy> pair = 555 (Pair<String, CarAppBlockingPolicy>) msg.obj; 556 doUpdatePolicy(pair.first, pair.second, msg.arg1); 557 break; 558 } 559 } 560 } 561 562 private static class AppBlockingPackageInfoWrapper { 563 private final AppBlockingPackageInfo info; 564 /** 565 * Whether the current info is matching with the target package in system. Mismatch can 566 * happen for version out of range or signature mismatch. 567 */ 568 private boolean isMatching; 569 AppBlockingPackageInfoWrapper(AppBlockingPackageInfo info, boolean isMatching)570 private AppBlockingPackageInfoWrapper(AppBlockingPackageInfo info, boolean isMatching) { 571 this.info =info; 572 this.isMatching = isMatching; 573 } 574 575 @Override toString()576 public String toString() { 577 return "AppBlockingPackageInfoWrapper [info=" + info + ", isMatching=" + isMatching + 578 "]"; 579 } 580 } 581 582 /** 583 * Client policy holder per each client. Should be accessed with CarpackageManagerService.this 584 * held. 585 */ 586 private static class ClientPolicy { 587 private final HashMap<String, AppBlockingPackageInfoWrapper> whitelistsMap = 588 new HashMap<>(); 589 private final HashMap<String, AppBlockingPackageInfoWrapper> blacklistsMap = 590 new HashMap<>(); 591 replaceWhitelists(AppBlockingPackageInfoWrapper[] whitelists)592 private void replaceWhitelists(AppBlockingPackageInfoWrapper[] whitelists) { 593 whitelistsMap.clear(); 594 addToWhitelists(whitelists); 595 } 596 addToWhitelists(AppBlockingPackageInfoWrapper[] whitelists)597 private void addToWhitelists(AppBlockingPackageInfoWrapper[] whitelists) { 598 if (whitelists == null) { 599 return; 600 } 601 for (AppBlockingPackageInfoWrapper wrapper : whitelists) { 602 if (wrapper != null) { 603 whitelistsMap.put(wrapper.info.packageName, wrapper); 604 } 605 } 606 } 607 removeWhitelists(AppBlockingPackageInfoWrapper[] whitelists)608 private void removeWhitelists(AppBlockingPackageInfoWrapper[] whitelists) { 609 if (whitelists == null) { 610 return; 611 } 612 for (AppBlockingPackageInfoWrapper wrapper : whitelists) { 613 if (wrapper != null) { 614 whitelistsMap.remove(wrapper.info.packageName); 615 } 616 } 617 } 618 replaceBlacklists(AppBlockingPackageInfoWrapper[] blacklists)619 private void replaceBlacklists(AppBlockingPackageInfoWrapper[] blacklists) { 620 blacklistsMap.clear(); 621 addToBlacklists(blacklists); 622 } 623 addToBlacklists(AppBlockingPackageInfoWrapper[] blacklists)624 private void addToBlacklists(AppBlockingPackageInfoWrapper[] blacklists) { 625 if (blacklists == null) { 626 return; 627 } 628 for (AppBlockingPackageInfoWrapper wrapper : blacklists) { 629 if (wrapper != null) { 630 blacklistsMap.put(wrapper.info.packageName, wrapper); 631 } 632 } 633 } 634 removeBlacklists(AppBlockingPackageInfoWrapper[] blacklists)635 private void removeBlacklists(AppBlockingPackageInfoWrapper[] blacklists) { 636 if (blacklists == null) { 637 return; 638 } 639 for (AppBlockingPackageInfoWrapper wrapper : blacklists) { 640 if (wrapper != null) { 641 blacklistsMap.remove(wrapper.info.packageName); 642 } 643 } 644 } 645 } 646 } 647