blob: be8b0d51bb8114ae5477dfd1cb570154bd4afb6c [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;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Binder;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import java.util.List;
/** Utility class */
public final class CarServiceUtils {
private static final String PACKAGE_NOT_FOUND = "Package not found:";
/** do not construct. static only */
private CarServiceUtils() {};
/**
* Check if package name passed belongs to UID for the current binder call.
* @param context
* @param packageName
*/
public static void assertPackageName(Context context, String packageName)
throws IllegalArgumentException, SecurityException {
if (packageName == null) {
throw new IllegalArgumentException("Package name null");
}
ApplicationInfo appInfo = null;
try {
appInfo = context.getPackageManager().getApplicationInfo(packageName,
0);
} catch (NameNotFoundException e) {
String msg = PACKAGE_NOT_FOUND + packageName;
Log.w(CarLog.TAG_SERVICE, msg, e);
throw new SecurityException(msg, e);
}
if (appInfo == null) {
throw new SecurityException(PACKAGE_NOT_FOUND + packageName);
}
int uid = Binder.getCallingUid();
if (uid != appInfo.uid) {
throw new SecurityException("Wrong package name:" + packageName +
", The package does not belong to caller's uid:" + uid);
}
}
/**
* Execute a runnable on the main thread
*
* @param action The code to run on the main thread.
*/
public static void runOnMain(Runnable action) {
runOnLooper(Looper.getMainLooper(), action);
}
/**
* Execute a runnable in the given looper
* @param looper Looper to run the action.
* @param action The code to run.
*/
public static void runOnLooper(Looper looper, Runnable action) {
new Handler(looper).post(action);
}
/**
* Execute a call on the application's main thread, blocking until it is
* complete. Useful for doing things that are not thread-safe, such as
* looking at or modifying the view hierarchy.
*
* @param action The code to run on the main thread.
*/
public static void runOnMainSync(Runnable action) {
runOnLooperSync(Looper.getMainLooper(), action);
}
/**
* Execute a call on the given Looper thread, blocking until it is
* complete.
*
* @param looper Looper to run the action.
* @param action The code to run on the main thread.
*/
public static void runOnLooperSync(Looper looper, Runnable action) {
if (Looper.myLooper() == looper) {
// requested thread is the same as the current thread. call directly.
action.run();
} else {
Handler handler = new Handler(looper);
SyncRunnable sr = new SyncRunnable(action);
handler.post(sr);
sr.waitForComplete();
}
}
private static final class SyncRunnable implements Runnable {
private final Runnable mTarget;
private volatile boolean mComplete = false;
public SyncRunnable(Runnable target) {
mTarget = target;
}
@Override
public void run() {
mTarget.run();
synchronized (this) {
mComplete = true;
notifyAll();
}
}
public void waitForComplete() {
synchronized (this) {
while (!mComplete) {
try {
wait();
} catch (InterruptedException e) {
}
}
}
}
}
public static float[] toFloatArray(List<Float> list) {
final int size = list.size();
final float[] array = new float[size];
for (int i = 0; i < size; ++i) {
array[i] = list.get(i);
}
return array;
}
public static int[] toIntArray(List<Integer> list) {
final int size = list.size();
final int[] array = new int[size];
for (int i = 0; i < size; ++i) {
array[i] = list.get(i);
}
return array;
}
public static byte[] toByteArray(List<Byte> list) {
final int size = list.size();
final byte[] array = new byte[size];
for (int i = 0; i < size; ++i) {
array[i] = list.get(i);
}
return array;
}
}