• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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