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