1ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung/*
2ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung * Copyright (C) 2015 The Android Open Source Project
3ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung *
4ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung * Licensed under the Apache License, Version 2.0 (the "License");
5ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung * you may not use this file except in compliance with the License.
6ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung * You may obtain a copy of the License at
7ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung *
8ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung *      http://www.apache.org/licenses/LICENSE-2.0
9ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung *
10ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung * Unless required by applicable law or agreed to in writing, software
11ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung * distributed under the License is distributed on an "AS IS" BASIS,
12ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung * See the License for the specific language governing permissions and
14ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung * limitations under the License.
15ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung */
16ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung
17ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoungpackage com.android.car;
18ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung
194aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Parkimport android.content.Context;
204aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Parkimport android.content.pm.ApplicationInfo;
214aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Parkimport android.content.pm.PackageManager.NameNotFoundException;
224aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Parkimport android.os.Binder;
2343cfff21932b23f0e382aa78ffc1bb053928b1c5Keun-young Parkimport android.os.Handler;
2443cfff21932b23f0e382aa78ffc1bb053928b1c5Keun-young Parkimport android.os.Looper;
254aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Parkimport android.util.Log;
264aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park
270d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsevimport java.util.List;
280d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev
29ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung/** Utility class */
3043cfff21932b23f0e382aa78ffc1bb053928b1c5Keun-young Parkpublic final class CarServiceUtils {
31ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung
324aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park    private static final String PACKAGE_NOT_FOUND = "Package not found:";
334aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park
3443cfff21932b23f0e382aa78ffc1bb053928b1c5Keun-young Park    /** do not construct. static only */
3543cfff21932b23f0e382aa78ffc1bb053928b1c5Keun-young Park    private CarServiceUtils() {};
3643cfff21932b23f0e382aa78ffc1bb053928b1c5Keun-young Park
374aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park    /**
384aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park     * Check if package name passed belongs to UID for the current binder call.
394aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park     * @param context
404aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park     * @param packageName
414aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park     */
423da3c6150b395fb0ae0ae83873086a4a34cc8b33Enrico Granata    public static void assertPackageName(Context context, String packageName)
434aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park            throws IllegalArgumentException, SecurityException {
444aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park        if (packageName == null) {
454aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park            throw new IllegalArgumentException("Package name null");
464aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park        }
474aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park        ApplicationInfo appInfo = null;
484aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park        try {
494aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park            appInfo = context.getPackageManager().getApplicationInfo(packageName,
504aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park                    0);
514aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park        } catch (NameNotFoundException e) {
524aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park            String msg = PACKAGE_NOT_FOUND + packageName;
534aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park            Log.w(CarLog.TAG_SERVICE, msg, e);
544aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park            throw new SecurityException(msg, e);
554aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park        }
564aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park        if (appInfo == null) {
574aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park            throw new SecurityException(PACKAGE_NOT_FOUND + packageName);
584aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park        }
594aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park        int uid = Binder.getCallingUid();
604aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park        if (uid != appInfo.uid) {
614aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park            throw new SecurityException("Wrong package name:" + packageName +
624aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park                    ", The package does not belong to caller's uid:" + uid);
634aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park        }
644aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park    }
6543cfff21932b23f0e382aa78ffc1bb053928b1c5Keun-young Park
6643cfff21932b23f0e382aa78ffc1bb053928b1c5Keun-young Park    /**
6743cfff21932b23f0e382aa78ffc1bb053928b1c5Keun-young Park     * Execute a runnable on the main thread
6843cfff21932b23f0e382aa78ffc1bb053928b1c5Keun-young Park     *
6943cfff21932b23f0e382aa78ffc1bb053928b1c5Keun-young Park     * @param action The code to run on the main thread.
7043cfff21932b23f0e382aa78ffc1bb053928b1c5Keun-young Park     */
7143cfff21932b23f0e382aa78ffc1bb053928b1c5Keun-young Park    public static void runOnMain(Runnable action) {
7243cfff21932b23f0e382aa78ffc1bb053928b1c5Keun-young Park        runOnLooper(Looper.getMainLooper(), action);
7343cfff21932b23f0e382aa78ffc1bb053928b1c5Keun-young Park    }
7443cfff21932b23f0e382aa78ffc1bb053928b1c5Keun-young Park
7543cfff21932b23f0e382aa78ffc1bb053928b1c5Keun-young Park    /**
7643cfff21932b23f0e382aa78ffc1bb053928b1c5Keun-young Park     * Execute a runnable in the given looper
7743cfff21932b23f0e382aa78ffc1bb053928b1c5Keun-young Park     * @param looper Looper to run the action.
7843cfff21932b23f0e382aa78ffc1bb053928b1c5Keun-young Park     * @param action The code to run.
7943cfff21932b23f0e382aa78ffc1bb053928b1c5Keun-young Park     */
8043cfff21932b23f0e382aa78ffc1bb053928b1c5Keun-young Park    public static void runOnLooper(Looper looper, Runnable action) {
8143cfff21932b23f0e382aa78ffc1bb053928b1c5Keun-young Park        new Handler(looper).post(action);
8243cfff21932b23f0e382aa78ffc1bb053928b1c5Keun-young Park    }
8343cfff21932b23f0e382aa78ffc1bb053928b1c5Keun-young Park
8443cfff21932b23f0e382aa78ffc1bb053928b1c5Keun-young Park    /**
8543cfff21932b23f0e382aa78ffc1bb053928b1c5Keun-young Park     * Execute a call on the application's main thread, blocking until it is
8643cfff21932b23f0e382aa78ffc1bb053928b1c5Keun-young Park     * complete.  Useful for doing things that are not thread-safe, such as
8743cfff21932b23f0e382aa78ffc1bb053928b1c5Keun-young Park     * looking at or modifying the view hierarchy.
8843cfff21932b23f0e382aa78ffc1bb053928b1c5Keun-young Park     *
8943cfff21932b23f0e382aa78ffc1bb053928b1c5Keun-young Park     * @param action The code to run on the main thread.
9043cfff21932b23f0e382aa78ffc1bb053928b1c5Keun-young Park     */
9143cfff21932b23f0e382aa78ffc1bb053928b1c5Keun-young Park    public static void runOnMainSync(Runnable action) {
9243cfff21932b23f0e382aa78ffc1bb053928b1c5Keun-young Park        runOnLooperSync(Looper.getMainLooper(), action);
9343cfff21932b23f0e382aa78ffc1bb053928b1c5Keun-young Park    }
9443cfff21932b23f0e382aa78ffc1bb053928b1c5Keun-young Park
9543cfff21932b23f0e382aa78ffc1bb053928b1c5Keun-young Park    /**
9643cfff21932b23f0e382aa78ffc1bb053928b1c5Keun-young Park     * Execute a call on the given Looper thread, blocking until it is
9743cfff21932b23f0e382aa78ffc1bb053928b1c5Keun-young Park     * complete.
9843cfff21932b23f0e382aa78ffc1bb053928b1c5Keun-young Park     *
9943cfff21932b23f0e382aa78ffc1bb053928b1c5Keun-young Park     * @param looper Looper to run the action.
10043cfff21932b23f0e382aa78ffc1bb053928b1c5Keun-young Park     * @param action The code to run on the main thread.
10143cfff21932b23f0e382aa78ffc1bb053928b1c5Keun-young Park     */
10243cfff21932b23f0e382aa78ffc1bb053928b1c5Keun-young Park    public static void runOnLooperSync(Looper looper, Runnable action) {
10343cfff21932b23f0e382aa78ffc1bb053928b1c5Keun-young Park        if (Looper.myLooper() == looper) {
10443cfff21932b23f0e382aa78ffc1bb053928b1c5Keun-young Park            // requested thread is the same as the current thread. call directly.
10543cfff21932b23f0e382aa78ffc1bb053928b1c5Keun-young Park            action.run();
10643cfff21932b23f0e382aa78ffc1bb053928b1c5Keun-young Park        } else {
10743cfff21932b23f0e382aa78ffc1bb053928b1c5Keun-young Park            Handler handler = new Handler(looper);
10843cfff21932b23f0e382aa78ffc1bb053928b1c5Keun-young Park            SyncRunnable sr = new SyncRunnable(action);
10943cfff21932b23f0e382aa78ffc1bb053928b1c5Keun-young Park            handler.post(sr);
11043cfff21932b23f0e382aa78ffc1bb053928b1c5Keun-young Park            sr.waitForComplete();
11143cfff21932b23f0e382aa78ffc1bb053928b1c5Keun-young Park        }
11243cfff21932b23f0e382aa78ffc1bb053928b1c5Keun-young Park    }
11343cfff21932b23f0e382aa78ffc1bb053928b1c5Keun-young Park
11443cfff21932b23f0e382aa78ffc1bb053928b1c5Keun-young Park    private static final class SyncRunnable implements Runnable {
11543cfff21932b23f0e382aa78ffc1bb053928b1c5Keun-young Park        private final Runnable mTarget;
11643cfff21932b23f0e382aa78ffc1bb053928b1c5Keun-young Park        private volatile boolean mComplete = false;
11743cfff21932b23f0e382aa78ffc1bb053928b1c5Keun-young Park
11843cfff21932b23f0e382aa78ffc1bb053928b1c5Keun-young Park        public SyncRunnable(Runnable target) {
11943cfff21932b23f0e382aa78ffc1bb053928b1c5Keun-young Park            mTarget = target;
12043cfff21932b23f0e382aa78ffc1bb053928b1c5Keun-young Park        }
12143cfff21932b23f0e382aa78ffc1bb053928b1c5Keun-young Park
12243cfff21932b23f0e382aa78ffc1bb053928b1c5Keun-young Park        @Override
12343cfff21932b23f0e382aa78ffc1bb053928b1c5Keun-young Park        public void run() {
12443cfff21932b23f0e382aa78ffc1bb053928b1c5Keun-young Park            mTarget.run();
12543cfff21932b23f0e382aa78ffc1bb053928b1c5Keun-young Park            synchronized (this) {
12643cfff21932b23f0e382aa78ffc1bb053928b1c5Keun-young Park                mComplete = true;
12743cfff21932b23f0e382aa78ffc1bb053928b1c5Keun-young Park                notifyAll();
12843cfff21932b23f0e382aa78ffc1bb053928b1c5Keun-young Park            }
12943cfff21932b23f0e382aa78ffc1bb053928b1c5Keun-young Park        }
13043cfff21932b23f0e382aa78ffc1bb053928b1c5Keun-young Park
13143cfff21932b23f0e382aa78ffc1bb053928b1c5Keun-young Park        public void waitForComplete() {
13243cfff21932b23f0e382aa78ffc1bb053928b1c5Keun-young Park            synchronized (this) {
13343cfff21932b23f0e382aa78ffc1bb053928b1c5Keun-young Park                while (!mComplete) {
13443cfff21932b23f0e382aa78ffc1bb053928b1c5Keun-young Park                    try {
13543cfff21932b23f0e382aa78ffc1bb053928b1c5Keun-young Park                        wait();
13643cfff21932b23f0e382aa78ffc1bb053928b1c5Keun-young Park                    } catch (InterruptedException e) {
13743cfff21932b23f0e382aa78ffc1bb053928b1c5Keun-young Park                    }
13843cfff21932b23f0e382aa78ffc1bb053928b1c5Keun-young Park                }
13943cfff21932b23f0e382aa78ffc1bb053928b1c5Keun-young Park            }
14043cfff21932b23f0e382aa78ffc1bb053928b1c5Keun-young Park        }
14143cfff21932b23f0e382aa78ffc1bb053928b1c5Keun-young Park    }
14271b2f5cd736f3a9aac8a9356b049d20ea76edb88Keun-young Park
14371b2f5cd736f3a9aac8a9356b049d20ea76edb88Keun-young Park    public static float[] toFloatArray(List<Float> list) {
14471b2f5cd736f3a9aac8a9356b049d20ea76edb88Keun-young Park        final int size = list.size();
14571b2f5cd736f3a9aac8a9356b049d20ea76edb88Keun-young Park        final float[] array = new float[size];
14671b2f5cd736f3a9aac8a9356b049d20ea76edb88Keun-young Park        for (int i = 0; i < size; ++i) {
14771b2f5cd736f3a9aac8a9356b049d20ea76edb88Keun-young Park            array[i] = list.get(i);
14871b2f5cd736f3a9aac8a9356b049d20ea76edb88Keun-young Park        }
14971b2f5cd736f3a9aac8a9356b049d20ea76edb88Keun-young Park        return array;
15071b2f5cd736f3a9aac8a9356b049d20ea76edb88Keun-young Park    }
15171b2f5cd736f3a9aac8a9356b049d20ea76edb88Keun-young Park
15271b2f5cd736f3a9aac8a9356b049d20ea76edb88Keun-young Park    public static int[] toIntArray(List<Integer> list) {
15371b2f5cd736f3a9aac8a9356b049d20ea76edb88Keun-young Park        final int size = list.size();
15471b2f5cd736f3a9aac8a9356b049d20ea76edb88Keun-young Park        final int[] array = new int[size];
15571b2f5cd736f3a9aac8a9356b049d20ea76edb88Keun-young Park        for (int i = 0; i < size; ++i) {
15671b2f5cd736f3a9aac8a9356b049d20ea76edb88Keun-young Park            array[i] = list.get(i);
15771b2f5cd736f3a9aac8a9356b049d20ea76edb88Keun-young Park        }
15871b2f5cd736f3a9aac8a9356b049d20ea76edb88Keun-young Park        return array;
15971b2f5cd736f3a9aac8a9356b049d20ea76edb88Keun-young Park    }
1600d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev
1610d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev    public static byte[] toByteArray(List<Byte> list) {
1620d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        final int size = list.size();
1630d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        final byte[] array = new byte[size];
1640d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        for (int i = 0; i < size; ++i) {
1650d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev            array[i] = list.get(i);
1660d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        }
1670d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        return array;
1680d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev    }
169ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung}
170