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.car.content.pm.CarAppBlockingPolicy;
     19 import android.car.content.pm.ICarAppBlockingPolicy;
     20 import android.car.content.pm.ICarAppBlockingPolicySetter;
     21 import android.content.ComponentName;
     22 import android.content.Context;
     23 import android.content.Intent;
     24 import android.content.ServiceConnection;
     25 import android.content.pm.ServiceInfo;
     26 import android.os.Handler;
     27 import android.os.IBinder;
     28 import android.os.RemoteException;
     29 import android.os.UserHandle;
     30 import android.util.Log;
     31 
     32 import com.android.car.CarLog;
     33 import com.android.internal.annotations.GuardedBy;
     34 
     35 public class AppBlockingPolicyProxy implements ServiceConnection {
     36 
     37     private final CarPackageManagerService mService;
     38     private final Context mContext;
     39     private final ServiceInfo mServiceInfo;
     40     private final ICarAppBlockingPolicySetterImpl mSetter;
     41 
     42     @GuardedBy("this")
     43     private ICarAppBlockingPolicy mPolicyService = null;
     44 
     45     /**
     46      * policy not set within this time after binding will be treated as failure and will be
     47      * ignored.
     48      */
     49     private static final long TIMEOUT_MS = 5000;
     50     private static final int MAX_CRASH_RETRY = 2;
     51     @GuardedBy("this")
     52     private int mCrashCount = 0;
     53     @GuardedBy("this")
     54     private boolean mBound = false;
     55 
     56     private final Handler mHandler;
     57     private final Runnable mTimeoutRunnable = new Runnable() {
     58         @Override
     59         public void run() {
     60             Log.w(CarLog.TAG_PACKAGE, "Timeout for policy setting for service:" + mServiceInfo);
     61             disconnect();
     62             mService.onPolicyConnectionFailure(AppBlockingPolicyProxy.this);
     63         }
     64     };
     65 
     66     public AppBlockingPolicyProxy(CarPackageManagerService service, Context context,
     67             ServiceInfo serviceInfo) {
     68         mService = service;
     69         mContext = context;
     70         mServiceInfo = serviceInfo;
     71         mSetter = new ICarAppBlockingPolicySetterImpl();
     72         mHandler = new Handler(mService.getLooper());
     73     }
     74 
     75     public String getPackageName() {
     76         return mServiceInfo.packageName;
     77     }
     78 
     79     public void connect() {
     80         Intent intent = new Intent();
     81         intent.setComponent(mServiceInfo.getComponentName());
     82         mContext.bindServiceAsUser(intent, this, Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT,
     83                 UserHandle.SYSTEM);
     84         synchronized (this) {
     85             mBound = true;
     86         }
     87         mHandler.postDelayed(mTimeoutRunnable, TIMEOUT_MS);
     88     }
     89 
     90     public void disconnect() {
     91         synchronized (this) {
     92             if (!mBound) {
     93                 return;
     94             }
     95             mBound = false;
     96             mPolicyService = null;
     97         }
     98         mHandler.removeCallbacks(mTimeoutRunnable);
     99         try {
    100             mContext.unbindService(this);
    101         } catch (IllegalArgumentException e) {
    102             Log.w(CarLog.TAG_PACKAGE, "unbind", e);
    103         }
    104     }
    105 
    106     @Override
    107     public void onServiceConnected(ComponentName name, IBinder service) {
    108         ICarAppBlockingPolicy policy = null;
    109         boolean failed = false;
    110         synchronized (this) {
    111             mPolicyService = ICarAppBlockingPolicy.Stub.asInterface(service);
    112             policy = mPolicyService;
    113             if (policy == null) {
    114                 failed = true;
    115             }
    116         }
    117         if (failed) {
    118             Log.w(CarLog.TAG_PACKAGE, "Policy service connected with null binder:" + name);
    119             mService.onPolicyConnectionFailure(this);
    120             return;
    121         }
    122         try {
    123             mPolicyService.setAppBlockingPolicySetter(mSetter);
    124         } catch (RemoteException e) {
    125             // let retry handle this
    126         }
    127     }
    128 
    129     @Override
    130     public void onServiceDisconnected(ComponentName name) {
    131         boolean failed = false;
    132         synchronized (this) {
    133             mCrashCount++;
    134             if (mCrashCount > MAX_CRASH_RETRY) {
    135                 mPolicyService = null;
    136                 failed = true;
    137             }
    138         }
    139         if (failed) {
    140             Log.w(CarLog.TAG_PACKAGE, "Policy service keep crashing, giving up:" + name);
    141             mService.onPolicyConnectionFailure(this);
    142         }
    143     }
    144 
    145     @Override
    146     public String toString() {
    147         return "AppBlockingPolicyProxy [mServiceInfo=" + mServiceInfo + ", mCrashCount="
    148                 + mCrashCount + "]";
    149     }
    150 
    151     private class ICarAppBlockingPolicySetterImpl extends ICarAppBlockingPolicySetter.Stub {
    152 
    153         @Override
    154         public void setAppBlockingPolicy(CarAppBlockingPolicy policy) {
    155             mHandler.removeCallbacks(mTimeoutRunnable);
    156             if (policy == null) {
    157                 Log.w(CarLog.TAG_PACKAGE, "setAppBlockingPolicy null policy from policy service:" +
    158                         mServiceInfo);
    159             }
    160             mService.onPolicyConnectionAndSet(AppBlockingPolicyProxy.this, policy);
    161         }
    162     }
    163 }
    164