/* * 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 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 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 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; } }