blob: 3ab7df408aebc8d382463185e17fff8e3fb71498 [file] [log] [blame]
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.car.pm;
import android.car.content.pm.CarAppBlockingPolicy;
import android.car.content.pm.ICarAppBlockingPolicy;
import android.car.content.pm.ICarAppBlockingPolicySetter;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.pm.ServiceInfo;
import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.UserHandle;
import android.util.Log;
import com.android.car.CarLog;
import com.android.internal.annotations.GuardedBy;
public class AppBlockingPolicyProxy implements ServiceConnection {
private final CarPackageManagerService mService;
private final Context mContext;
private final ServiceInfo mServiceInfo;
private final ICarAppBlockingPolicySetterImpl mSetter;
@GuardedBy("this")
private ICarAppBlockingPolicy mPolicyService = null;
/**
* policy not set within this time after binding will be treated as failure and will be
* ignored.
*/
private static final long TIMEOUT_MS = 5000;
private static final int MAX_CRASH_RETRY = 2;
@GuardedBy("this")
private int mCrashCount = 0;
@GuardedBy("this")
private boolean mBound = false;
private final Handler mHandler;
private final Runnable mTimeoutRunnable = new Runnable() {
@Override
public void run() {
Log.w(CarLog.TAG_PACKAGE, "Timeout for policy setting for service:" + mServiceInfo);
disconnect();
mService.onPolicyConnectionFailure(AppBlockingPolicyProxy.this);
}
};
public AppBlockingPolicyProxy(CarPackageManagerService service, Context context,
ServiceInfo serviceInfo) {
mService = service;
mContext = context;
mServiceInfo = serviceInfo;
mSetter = new ICarAppBlockingPolicySetterImpl();
mHandler = new Handler(mService.getLooper());
}
public String getPackageName() {
return mServiceInfo.packageName;
}
public void connect() {
Intent intent = new Intent();
intent.setClassName(mServiceInfo.packageName, mServiceInfo.name);
mContext.bindServiceAsUser(intent, this, Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT,
UserHandle.SYSTEM);
synchronized (this) {
mBound = true;
}
mHandler.postDelayed(mTimeoutRunnable, TIMEOUT_MS);
}
public void disconnect() {
synchronized (this) {
if (!mBound) {
return;
}
mBound = false;
mPolicyService = null;
}
mHandler.removeCallbacks(mTimeoutRunnable);
try {
mContext.unbindService(this);
} catch (IllegalArgumentException e) {
Log.w(CarLog.TAG_PACKAGE, "unbind", e);
}
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
ICarAppBlockingPolicy policy = null;
boolean failed = false;
synchronized (this) {
mPolicyService = ICarAppBlockingPolicy.Stub.asInterface(service);
policy = mPolicyService;
if (policy == null) {
failed = true;
}
}
if (failed) {
Log.w(CarLog.TAG_PACKAGE, "Policy service connected with null binder:" + name);
mService.onPolicyConnectionFailure(this);
return;
}
try {
mPolicyService.setAppBlockingPolicySetter(mSetter);
} catch (RemoteException e) {
// let retry handle this
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
boolean failed = false;
synchronized (this) {
mCrashCount++;
if (mCrashCount > MAX_CRASH_RETRY) {
mPolicyService = null;
failed = true;
}
}
if (failed) {
Log.w(CarLog.TAG_PACKAGE, "Policy service keep crashing, giving up:" + name);
mService.onPolicyConnectionFailure(this);
}
}
@Override
public String toString() {
return "AppBlockingPolicyProxy [mServiceInfo=" + mServiceInfo + ", mCrashCount="
+ mCrashCount + "]";
}
private class ICarAppBlockingPolicySetterImpl extends ICarAppBlockingPolicySetter.Stub {
@Override
public void setAppBlockingPolicy(CarAppBlockingPolicy policy) {
mHandler.removeCallbacks(mTimeoutRunnable);
if (policy == null) {
Log.w(CarLog.TAG_PACKAGE, "setAppBlockingPolicy null policy from policy service:" +
mServiceInfo);
}
mService.onPolicyConnectionAndSet(AppBlockingPolicyProxy.this, policy);
}
}
}