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