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