blob: 98c582200735a0ca760ec659224c547607a0f82c [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 android.car.content.pm;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.annotation.TestApi;
import android.app.PendingIntent;
import android.car.Car;
import android.car.CarManagerBase;
import android.content.ComponentName;
import android.os.IBinder;
import android.os.Looper;
import android.os.RemoteException;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
* Provides car specific API related with package management.
*/
public final class CarPackageManager extends CarManagerBase {
private static final String TAG = "CarPackageManager";
/**
* Flag for {@link #setAppBlockingPolicy(String, CarAppBlockingPolicy, int)}. When this
* flag is set, the call will be blocked until policy is set to system. This can take time
* and the flag cannot be used in main thread.
* @hide
*/
@SystemApi
public static final int FLAG_SET_POLICY_WAIT_FOR_CHANGE = 0x1;
/**
* Flag for {@link #setAppBlockingPolicy(String, CarAppBlockingPolicy, int)}. When this
* flag is set, passed policy is added to existing policy set from the current package.
* If none of {@link #FLAG_SET_POLICY_ADD} or {@link #FLAG_SET_POLICY_REMOVE} is set, existing
* policy is replaced. Note that policy per each package is always replaced and will not be
* added.
* @hide
*/
@SystemApi
public static final int FLAG_SET_POLICY_ADD = 0x2;
/**
* Flag for {@link #setAppBlockingPolicy(String, CarAppBlockingPolicy, int)}. When this
* flag is set, passed policy is removed from existing policy set from the current package.
* If none of {@link #FLAG_SET_POLICY_ADD} or {@link #FLAG_SET_POLICY_REMOVE} is set, existing
* policy is replaced.
* @hide
*/
@SystemApi
public static final int FLAG_SET_POLICY_REMOVE = 0x4;
/** @hide */
@IntDef(flag = true,
value = {FLAG_SET_POLICY_WAIT_FOR_CHANGE, FLAG_SET_POLICY_ADD, FLAG_SET_POLICY_REMOVE})
@Retention(RetentionPolicy.SOURCE)
public @interface SetPolicyFlags {}
private final ICarPackageManager mService;
/** @hide */
public CarPackageManager(Car car, IBinder service) {
super(car);
mService = ICarPackageManager.Stub.asInterface(service);
}
/** @hide */
@Override
public void onCarDisconnected() {
// nothing to do
}
/**
* Set Application blocking policy for system app. {@link #FLAG_SET_POLICY_ADD} or
* {@link #FLAG_SET_POLICY_REMOVE} flag allows adding or removing from already set policy. When
* none of these flags are set, it will completely replace existing policy for each package
* specified.
* When {@link #FLAG_SET_POLICY_WAIT_FOR_CHANGE} flag is set, this call will be blocked
* until the policy is set to system and become effective. Otherwise, the call will start
* changing the policy but it will be completed asynchronously and the call will return
* without waiting for system level policy change.
*
* @param packageName Package name of the client. If wrong package name is passed, exception
* will be thrown. This name is used to update the policy.
* @param policy
* @param flags
* @throws SecurityException if caller has no permission.
* @throws IllegalArgumentException For wrong or invalid arguments.
* @throws IllegalStateException If {@link #FLAG_SET_POLICY_WAIT_FOR_CHANGE} is set while
* called from main thread.
* @hide
*/
@SystemApi
public void setAppBlockingPolicy(
String packageName, CarAppBlockingPolicy policy, @SetPolicyFlags int flags) {
if ((flags & FLAG_SET_POLICY_WAIT_FOR_CHANGE) != 0
&& Looper.getMainLooper().isCurrentThread()) {
throw new IllegalStateException(
"FLAG_SET_POLICY_WAIT_FOR_CHANGE cannot be used in main thread");
}
try {
mService.setAppBlockingPolicy(packageName, policy, flags);
} catch (RemoteException e) {
handleRemoteExceptionFromCarService(e);
}
}
/**
* Restarts the requested task. If task with {@code taskId} does not exist, do nothing.
*
* @hide
*/
public void restartTask(int taskId) {
try {
mService.restartTask(taskId);
} catch (RemoteException e) {
handleRemoteExceptionFromCarService(e);
}
}
/**
* Check if finishing Activity will lead into safe Activity (=allowed Activity) to be shown.
* This can be used by unsafe activity blocking Activity to check if finishing itself can
* lead into being launched again due to unsafe activity shown. Note that checking this does not
* guarantee that blocking will not be done as driving state can change after this call is made.
*
* @param activityName
* @return true if there is a safe Activity (or car is stopped) in the back of task stack
* so that finishing the Activity will not trigger another Activity blocking. If
* the given Activity is not in foreground, then it will return true as well as
* finishing the Activity will not make any difference.
*
* @hide
*/
@SystemApi
public boolean isActivityBackedBySafeActivity(ComponentName activityName) {
try {
return mService.isActivityBackedBySafeActivity(activityName);
} catch (RemoteException e) {
return handleRemoteExceptionFromCarService(e, false);
}
}
/**
* Enable/Disable Activity Blocking. This is to provide an option for toggling app blocking
* behavior for development purposes.
* @hide
*/
@TestApi
public void setEnableActivityBlocking(boolean enable) {
try {
mService.setEnableActivityBlocking(enable);
} catch (RemoteException e) {
handleRemoteExceptionFromCarService(e);
}
}
/**
* Returns whether an activity is distraction optimized, i.e, allowed in a restricted
* driving state.
*
* @param packageName the activity's {@link android.content.pm.ActivityInfo#packageName}.
* @param className the activity's {@link android.content.pm.ActivityInfo#name}.
* @return true if the activity is distraction optimized, false if it isn't or if the value
* could not be determined.
*/
public boolean isActivityDistractionOptimized(String packageName, String className) {
try {
return mService.isActivityDistractionOptimized(packageName, className);
} catch (RemoteException e) {
return handleRemoteExceptionFromCarService(e, false);
}
}
/**
* Returns whether the given {@link PendingIntent} represents an activity that is distraction
* optimized, i.e, allowed in a restricted driving state.
*
* @param pendingIntent the {@link PendingIntent} to check.
* @return true if the pending intent represents an activity that is distraction optimized,
* false if it isn't or if the value could not be determined.
*/
public boolean isPendingIntentDistractionOptimized(@NonNull PendingIntent pendingIntent) {
try {
return mService.isPendingIntentDistractionOptimized(pendingIntent);
} catch (RemoteException e) {
return handleRemoteExceptionFromCarService(e, false);
}
}
/**
* Check if given service is distraction optimized, i.e, allowed in a restricted
* driving state.
*
* @param packageName
* @param className
* @return
*/
public boolean isServiceDistractionOptimized(String packageName, String className) {
try {
return mService.isServiceDistractionOptimized(packageName, className);
} catch (RemoteException e) {
return handleRemoteExceptionFromCarService(e, false);
}
}
}