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 
CarPackageManagerService(Context context, CarSensorService sensorService, SystemActivityMonitoringService systemActivityMonitoringService)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
setAppBlockingPolicy(String packageName, CarAppBlockingPolicy policy, int flags)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 
doSetAppBlockingPolicy(String packageName, CarAppBlockingPolicy policy, int flags, boolean setNow)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
isActivityAllowedWhileDriving(String packageName, String className)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
isServiceAllowedWhileDriving(String packageName, String className)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
isActivityBackedBySafeActivity(ComponentName activityName)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 
getLooper()210     public Looper getLooper() {
211         return mHandlerThread.getLooper();
212     }
213 
assertPackageAndClassName(String packageName, String className)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 
searchFromBlacklistsLocked(String packageName)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 
searchFromWhitelistsLocked(String packageName)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 
isActivityInWhitelistsLocked(String packageName, String className)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 
isActivityInMapAndMatching(HashMap<String, AppBlockingPackageInfoWrapper> map, String packageName, String className)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
init()263     public void init() {
264         if (!mEnableActivityBlocking) {
265             return;
266         }
267         synchronized (this) {
268             mHandler.requestInit();
269         }
270     }
271 
272     @Override
release()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
doHandleInit()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 
doHandleRelease()317     private synchronized void doHandleRelease() {
318         notifyAll();
319     }
320 
wakeupClientsWaitingForPolicySetitngLocked()321     private void wakeupClientsWaitingForPolicySetitngLocked() {
322         for (CarAppBlockingPolicy waitingPolicy : mWaitingPolicies) {
323             synchronized (waitingPolicy) {
324                 waitingPolicy.notifyAll();
325             }
326         }
327         mWaitingPolicies.clear();
328     }
329 
doSetPolicy()330     private void doSetPolicy() {
331         synchronized (this) {
332             wakeupClientsWaitingForPolicySetitngLocked();
333         }
334         blockTopActivitiesIfNecessary();
335     }
336 
doUpdatePolicy(String packageName, CarAppBlockingPolicy policy, int flags)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 
verifyList(AppBlockingPackageInfo[] list)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 
isInstalledPackageMatching(AppBlockingPackageInfo info)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      */
isAnySignatureMatching(Signature[] fromPackage, Signature[] fromPolicy)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      */
parseConfigWhitelist()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 
generateSystemWhitelists()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 
startAppBlockingPolicies()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 
onPolicyConnectionAndSet(AppBlockingPolicyProxy proxy, CarAppBlockingPolicy policy)560     public void onPolicyConnectionAndSet(AppBlockingPolicyProxy proxy,
561             CarAppBlockingPolicy policy) {
562         doHandlePolicyConnection(proxy, policy);
563     }
564 
onPolicyConnectionFailure(AppBlockingPolicyProxy proxy)565     public void onPolicyConnectionFailure(AppBlockingPolicyProxy proxy) {
566         doHandlePolicyConnection(proxy, null);
567     }
568 
doHandlePolicyConnection(AppBlockingPolicyProxy proxy, CarAppBlockingPolicy policy)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
dump(PrintWriter writer)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 
dumpPoliciesLocked(boolean dumpAll)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 
blockTopActivityIfNecessary(TopTaskInfoContainer topTask)641     private void blockTopActivityIfNecessary(TopTaskInfoContainer topTask) {
642         boolean restricted = mDrivingStateListener.isRestricted();
643         if (!restricted) {
644             return;
645         }
646         doBlockTopActivityIfNotAllowed(topTask);
647     }
648 
doBlockTopActivityIfNotAllowed(TopTaskInfoContainer topTask)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 
blockTopActivitiesIfNecessary()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 
PackageHandler(Looper looper)689         private PackageHandler(Looper looper) {
690             super(looper);
691         }
692 
requestInit()693         private void requestInit() {
694             Message msg = obtainMessage(MSG_INIT);
695             sendMessage(msg);
696         }
697 
requestRelease()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 
requestPolicySetting()706         private void requestPolicySetting() {
707             Message msg = obtainMessage(MSG_SET_POLICY);
708             sendMessage(msg);
709         }
710 
requestUpdatingPolicy(String packageName, CarAppBlockingPolicy policy, int flags)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
handleMessage(Message msg)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 
AppBlockingPackageInfoWrapper(AppBlockingPackageInfo info, boolean isMatching)747         private AppBlockingPackageInfoWrapper(AppBlockingPackageInfo info, boolean isMatching) {
748             this.info =info;
749             this.isMatching = isMatching;
750         }
751 
752         @Override
toString()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 
replaceWhitelists(AppBlockingPackageInfoWrapper[] whitelists)769         private void replaceWhitelists(AppBlockingPackageInfoWrapper[] whitelists) {
770             whitelistsMap.clear();
771             addToWhitelists(whitelists);
772         }
773 
addToWhitelists(AppBlockingPackageInfoWrapper[] whitelists)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 
removeWhitelists(AppBlockingPackageInfoWrapper[] whitelists)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 
replaceBlacklists(AppBlockingPackageInfoWrapper[] blacklists)796         private void replaceBlacklists(AppBlockingPackageInfoWrapper[] blacklists) {
797             blacklistsMap.clear();
798             addToBlacklists(blacklists);
799         }
800 
addToBlacklists(AppBlockingPackageInfoWrapper[] blacklists)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 
removeBlacklists(AppBlockingPackageInfoWrapper[] blacklists)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
onActivityLaunch(TopTaskInfoContainer topTask)827         public void onActivityLaunch(TopTaskInfoContainer topTask) {
828             blockTopActivityIfNecessary(topTask);
829         }
830     }
831 
832     private class SensorListener extends ICarSensorEventListener.Stub {
833         private int mLatestDrivingState;
834 
resetState()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 
isRestricted()856         private synchronized boolean isRestricted() {
857             return mLatestDrivingState != CarSensorEvent.DRIVE_STATUS_UNRESTRICTED;
858         }
859 
860         @Override
onSensorChanged(List<CarSensorEvent> events)861         public void onSensorChanged(List<CarSensorEvent> events) {
862             resetState();
863         }
864     }
865 }
866