14aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park/* 24aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park * Copyright (C) 2015 The Android Open Source Project 34aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park * 44aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park * Licensed under the Apache License, Version 2.0 (the "License"); 54aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park * you may not use this file except in compliance with the License. 64aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park * You may obtain a copy of the License at 74aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park * 84aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park * http://www.apache.org/licenses/LICENSE-2.0 94aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park * 104aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park * Unless required by applicable law or agreed to in writing, software 114aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park * distributed under the License is distributed on an "AS IS" BASIS, 124aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 134aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park * See the License for the specific language governing permissions and 144aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park * limitations under the License. 154aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park */ 164aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Parkpackage com.android.car.pm; 174aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park 18e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Parkimport android.car.content.pm.CarAppBlockingPolicy; 19e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Parkimport android.car.content.pm.ICarAppBlockingPolicy; 20e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Parkimport android.car.content.pm.ICarAppBlockingPolicySetter; 214aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Parkimport android.content.ComponentName; 224aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Parkimport android.content.Context; 234aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Parkimport android.content.Intent; 244aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Parkimport android.content.ServiceConnection; 254aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Parkimport android.content.pm.ServiceInfo; 264aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Parkimport android.os.Handler; 274aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Parkimport android.os.IBinder; 284aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Parkimport android.os.RemoteException; 294aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Parkimport android.os.UserHandle; 304aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Parkimport android.util.Log; 314aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park 324aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Parkimport com.android.car.CarLog; 334aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Parkimport com.android.internal.annotations.GuardedBy; 344aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park 354aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Parkpublic class AppBlockingPolicyProxy implements ServiceConnection { 364aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park 374aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park private final CarPackageManagerService mService; 384aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park private final Context mContext; 394aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park private final ServiceInfo mServiceInfo; 404aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park private final ICarAppBlockingPolicySetterImpl mSetter; 414aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park 424aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park @GuardedBy("this") 434aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park private ICarAppBlockingPolicy mPolicyService = null; 444aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park 454aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park /** 464aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park * policy not set within this time after binding will be treated as failure and will be 474aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park * ignored. 484aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park */ 494aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park private static final long TIMEOUT_MS = 5000; 504aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park private static final int MAX_CRASH_RETRY = 2; 514aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park @GuardedBy("this") 524aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park private int mCrashCount = 0; 534aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park @GuardedBy("this") 544aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park private boolean mBound = false; 554aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park 564aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park private final Handler mHandler; 574aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park private final Runnable mTimeoutRunnable = new Runnable() { 584aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park @Override 594aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park public void run() { 604aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park Log.w(CarLog.TAG_PACKAGE, "Timeout for policy setting for service:" + mServiceInfo); 614aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park disconnect(); 624aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park mService.onPolicyConnectionFailure(AppBlockingPolicyProxy.this); 634aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park } 644aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park }; 654aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park 664aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park public AppBlockingPolicyProxy(CarPackageManagerService service, Context context, 674aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park ServiceInfo serviceInfo) { 684aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park mService = service; 694aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park mContext = context; 704aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park mServiceInfo = serviceInfo; 714aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park mSetter = new ICarAppBlockingPolicySetterImpl(); 724aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park mHandler = new Handler(mService.getLooper()); 734aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park } 744aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park 754aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park public String getPackageName() { 764aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park return mServiceInfo.packageName; 774aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park } 784aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park 794aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park public void connect() { 804aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park Intent intent = new Intent(); 814aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park intent.setClassName(mServiceInfo.packageName, mServiceInfo.name); 824aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park mContext.bindServiceAsUser(intent, this, Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT, 834aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park UserHandle.SYSTEM); 844aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park synchronized (this) { 854aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park mBound = true; 864aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park } 874aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park mHandler.postDelayed(mTimeoutRunnable, TIMEOUT_MS); 884aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park } 894aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park 904aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park public void disconnect() { 914aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park synchronized (this) { 924aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park if (!mBound) { 934aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park return; 944aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park } 954aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park mBound = false; 964aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park mPolicyService = null; 974aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park } 984aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park mHandler.removeCallbacks(mTimeoutRunnable); 994aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park try { 1004aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park mContext.unbindService(this); 1014aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park } catch (IllegalArgumentException e) { 1024aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park Log.w(CarLog.TAG_PACKAGE, "unbind", e); 1034aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park } 1044aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park } 1054aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park 1064aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park @Override 1074aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park public void onServiceConnected(ComponentName name, IBinder service) { 1084aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park ICarAppBlockingPolicy policy = null; 1094aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park boolean failed = false; 1104aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park synchronized (this) { 1114aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park mPolicyService = ICarAppBlockingPolicy.Stub.asInterface(service); 1124aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park policy = mPolicyService; 1134aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park if (policy == null) { 1144aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park failed = true; 1154aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park } 1164aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park } 1174aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park if (failed) { 1184aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park Log.w(CarLog.TAG_PACKAGE, "Policy service connected with null binder:" + name); 1194aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park mService.onPolicyConnectionFailure(this); 1204aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park return; 1214aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park } 1224aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park try { 1234aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park mPolicyService.setAppBlockingPolicySetter(mSetter); 1244aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park } catch (RemoteException e) { 1254aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park // let retry handle this 1264aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park } 1274aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park } 1284aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park 1294aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park @Override 1304aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park public void onServiceDisconnected(ComponentName name) { 1314aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park boolean failed = false; 1324aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park synchronized (this) { 1334aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park mCrashCount++; 1344aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park if (mCrashCount > MAX_CRASH_RETRY) { 1354aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park mPolicyService = null; 1364aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park failed = true; 1374aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park } 1384aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park } 1394aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park if (failed) { 1404aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park Log.w(CarLog.TAG_PACKAGE, "Policy service keep crashing, giving up:" + name); 1414aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park mService.onPolicyConnectionFailure(this); 1424aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park } 1434aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park } 1444aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park 1454aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park @Override 1464aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park public String toString() { 1474aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park return "AppBlockingPolicyProxy [mServiceInfo=" + mServiceInfo + ", mCrashCount=" 1484aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park + mCrashCount + "]"; 1494aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park } 1504aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park 1514aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park private class ICarAppBlockingPolicySetterImpl extends ICarAppBlockingPolicySetter.Stub { 1524aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park 1534aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park @Override 1544aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park public void setAppBlockingPolicy(CarAppBlockingPolicy policy) { 1554aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park mHandler.removeCallbacks(mTimeoutRunnable); 1564aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park if (policy == null) { 1574aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park Log.w(CarLog.TAG_PACKAGE, "setAppBlockingPolicy null policy from policy service:" + 1584aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park mServiceInfo); 1594aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park } 1604aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park mService.onPolicyConnectionAndSet(AppBlockingPolicyProxy.this, policy); 1614aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park } 1624aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park } 1634aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park} 164