1 /*
2  * Copyright (C) 2015 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.car;
18 
19 import android.content.Context;
20 import android.content.pm.ApplicationInfo;
21 import android.content.pm.PackageManager.NameNotFoundException;
22 import android.os.Binder;
23 import android.os.Handler;
24 import android.os.Looper;
25 import android.util.Log;
26 
27 import java.util.List;
28 
29 /** Utility class */
30 public final class CarServiceUtils {
31 
32     private static final String PACKAGE_NOT_FOUND = "Package not found:";
33 
34     /** do not construct. static only */
CarServiceUtils()35     private CarServiceUtils() {};
36 
37     /**
38      * Check if package name passed belongs to UID for the current binder call.
39      * @param context
40      * @param packageName
41      */
assertPackageName(Context context, String packageName)42     public static void assertPackageName(Context context, String packageName)
43             throws IllegalArgumentException, SecurityException {
44         if (packageName == null) {
45             throw new IllegalArgumentException("Package name null");
46         }
47         ApplicationInfo appInfo = null;
48         try {
49             appInfo = context.getPackageManager().getApplicationInfo(packageName,
50                     0);
51         } catch (NameNotFoundException e) {
52             String msg = PACKAGE_NOT_FOUND + packageName;
53             Log.w(CarLog.TAG_SERVICE, msg, e);
54             throw new SecurityException(msg, e);
55         }
56         if (appInfo == null) {
57             throw new SecurityException(PACKAGE_NOT_FOUND + packageName);
58         }
59         int uid = Binder.getCallingUid();
60         if (uid != appInfo.uid) {
61             throw new SecurityException("Wrong package name:" + packageName +
62                     ", The package does not belong to caller's uid:" + uid);
63         }
64     }
65 
66     /**
67      * Execute a runnable on the main thread
68      *
69      * @param action The code to run on the main thread.
70      */
runOnMain(Runnable action)71     public static void runOnMain(Runnable action) {
72         runOnLooper(Looper.getMainLooper(), action);
73     }
74 
75     /**
76      * Execute a runnable in the given looper
77      * @param looper Looper to run the action.
78      * @param action The code to run.
79      */
runOnLooper(Looper looper, Runnable action)80     public static void runOnLooper(Looper looper, Runnable action) {
81         new Handler(looper).post(action);
82     }
83 
84     /**
85      * Execute a call on the application's main thread, blocking until it is
86      * complete.  Useful for doing things that are not thread-safe, such as
87      * looking at or modifying the view hierarchy.
88      *
89      * @param action The code to run on the main thread.
90      */
runOnMainSync(Runnable action)91     public static void runOnMainSync(Runnable action) {
92         runOnLooperSync(Looper.getMainLooper(), action);
93     }
94 
95     /**
96      * Execute a call on the given Looper thread, blocking until it is
97      * complete.
98      *
99      * @param looper Looper to run the action.
100      * @param action The code to run on the main thread.
101      */
runOnLooperSync(Looper looper, Runnable action)102     public static void runOnLooperSync(Looper looper, Runnable action) {
103         if (Looper.myLooper() == looper) {
104             // requested thread is the same as the current thread. call directly.
105             action.run();
106         } else {
107             Handler handler = new Handler(looper);
108             SyncRunnable sr = new SyncRunnable(action);
109             handler.post(sr);
110             sr.waitForComplete();
111         }
112     }
113 
114     private static final class SyncRunnable implements Runnable {
115         private final Runnable mTarget;
116         private volatile boolean mComplete = false;
117 
SyncRunnable(Runnable target)118         public SyncRunnable(Runnable target) {
119             mTarget = target;
120         }
121 
122         @Override
run()123         public void run() {
124             mTarget.run();
125             synchronized (this) {
126                 mComplete = true;
127                 notifyAll();
128             }
129         }
130 
waitForComplete()131         public void waitForComplete() {
132             synchronized (this) {
133                 while (!mComplete) {
134                     try {
135                         wait();
136                     } catch (InterruptedException e) {
137                     }
138                 }
139             }
140         }
141     }
142 
toFloatArray(List<Float> list)143     public static float[] toFloatArray(List<Float> list) {
144         final int size = list.size();
145         final float[] array = new float[size];
146         for (int i = 0; i < size; ++i) {
147             array[i] = list.get(i);
148         }
149         return array;
150     }
151 
toIntArray(List<Integer> list)152     public static int[] toIntArray(List<Integer> list) {
153         final int size = list.size();
154         final int[] array = new int[size];
155         for (int i = 0; i < size; ++i) {
156             array[i] = list.get(i);
157         }
158         return array;
159     }
160 
toByteArray(List<Byte> list)161     public static byte[] toByteArray(List<Byte> list) {
162         final int size = list.size();
163         final byte[] array = new byte[size];
164         for (int i = 0; i < size; ++i) {
165             array[i] = list.get(i);
166         }
167         return array;
168     }
169 }
170