Merge "Add projected texture support to evs_app"
diff --git a/service/AndroidManifest.xml b/service/AndroidManifest.xml
index 83d023d..263c83a 100644
--- a/service/AndroidManifest.xml
+++ b/service/AndroidManifest.xml
@@ -139,6 +139,7 @@
<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.DEVICE_POWER" />
+ <uses-permission android:name="android.permission.GRANT_RUNTIME_PERMISSIONS" />
<uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" />
<uses-permission android:name="android.permission.MANAGE_ACTIVITY_STACKS" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_ROUTING" />
diff --git a/service/res/values/config.xml b/service/res/values/config.xml
index c24e58e..fd4a841 100644
--- a/service/res/values/config.xml
+++ b/service/res/values/config.xml
@@ -77,4 +77,8 @@
<!-- The com.android.car.VmsPublisherService will bind to this list of clients -->
<string-array translatable="false" name="vmsPublisherClients">
</string-array>
+ <!-- Permissions that the com.android.car.VmsPublisherService is allowed to grant to publishers -->
+ <string-array translatable="false" name="vmsSafePermissions">
+ <item>"android.permission.ACCESS_FINE_LOCATION"</item>
+ </string-array>
</resources>
diff --git a/service/src/com/android/car/VmsPublisherService.java b/service/src/com/android/car/VmsPublisherService.java
index 8bb0167..683c1c8 100644
--- a/service/src/com/android/car/VmsPublisherService.java
+++ b/service/src/com/android/car/VmsPublisherService.java
@@ -27,9 +27,12 @@
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
+import android.os.UserHandle;
import android.text.TextUtils;
import android.util.Log;
import com.android.car.hal.VmsHalService;
@@ -37,7 +40,9 @@
import java.io.PrintWriter;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -56,6 +61,7 @@
private final Context mContext;
private final VmsHalService mHal;
private final VmsPublisherManager mPublisherManager;
+ private Set<String> mSafePermissions;
public VmsPublisherService(Context context, VmsHalService hal) {
mContext = context;
@@ -67,6 +73,9 @@
@Override
public void init() {
mHal.addPublisherListener(this);
+ // Load permissions that can be granted to publishers.
+ mSafePermissions = new HashSet<>(
+ Arrays.asList(mContext.getResources().getStringArray(R.array.vmsSafePermissions)));
// Launch publishers.
String[] publisherNames = mContext.getResources().getStringArray(
R.array.vmsPublisherClients);
@@ -187,11 +196,12 @@
// Already registered, nothing to do.
return;
}
+ grantPermissions(name);
Intent intent = new Intent();
intent.setComponent(name);
PublisherConnection connection = new PublisherConnection();
- if (publisherService.mContext.bindService(intent, connection,
- Context.BIND_AUTO_CREATE)) {
+ if (publisherService.mContext.bindServiceAsUser(intent, connection,
+ Context.BIND_AUTO_CREATE, UserHandle.SYSTEM)) {
mPublisherConnectionMap.put(publisherName, connection);
} else {
Log.e(TAG, "unable to bind to: " + publisherName);
@@ -244,6 +254,39 @@
mPublisherMap.clear();
}
+ private void grantPermissions(ComponentName component) {
+ VmsPublisherService publisherService = mPublisherService.get();
+ if (publisherService == null) return;
+ final PackageManager packageManager = publisherService.mContext.getPackageManager();
+ final String packageName = component.getPackageName();
+ PackageInfo packageInfo;
+ try {
+ packageInfo = packageManager.getPackageInfo(packageName,
+ PackageManager.GET_PERMISSIONS);
+ } catch (PackageManager.NameNotFoundException e) {
+ Log.e(TAG, "Error getting package info for " + packageName, e);
+ return;
+ }
+ if (packageInfo.requestedPermissions == null) return;
+ for (String permission : packageInfo.requestedPermissions) {
+ if (!publisherService.mSafePermissions.contains(permission)) {
+ continue;
+ }
+ if (packageManager.checkPermission(permission, packageName)
+ == PackageManager.PERMISSION_GRANTED) {
+ continue;
+ }
+ try {
+ packageManager.grantRuntimePermission(packageName, permission,
+ UserHandle.SYSTEM);
+ Log.d(TAG, "Permission " + permission + " granted to " + packageName);
+ } catch (SecurityException | IllegalArgumentException e) {
+ Log.e(TAG, "Error while trying to grant " + permission + " to " + packageName,
+ e);
+ }
+ }
+ }
+
class PublisherConnection implements ServiceConnection {
private final IBinder mToken = new Binder();
diff --git a/tests/EmbeddedKitchenSinkApp/Android.mk b/tests/EmbeddedKitchenSinkApp/Android.mk
index 57a0620..d661902 100644
--- a/tests/EmbeddedKitchenSinkApp/Android.mk
+++ b/tests/EmbeddedKitchenSinkApp/Android.mk
@@ -14,6 +14,9 @@
#
#
+#disble build in PDK, missing ui-lib breaks build
+ifneq ($(TARGET_BUILD_PDK),true)
+
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
@@ -47,3 +50,5 @@
include packages/services/Car/car-support-lib/car-support.mk
include $(BUILD_PACKAGE)
+
+endif #TARGET_BUILD_PDK
diff --git a/tests/VmsPublisherClientSample/Android.mk b/tests/VmsPublisherClientSample/Android.mk
index 6bb5bf7..2aa6c40 100644
--- a/tests/VmsPublisherClientSample/Android.mk
+++ b/tests/VmsPublisherClientSample/Android.mk
@@ -28,7 +28,7 @@
LOCAL_PRIVILEGED_MODULE := true
-LOCAL_CERTIFICATE := platform
+LOCAL_CERTIFICATE := testkey
LOCAL_PROGUARD_ENABLED := disabled
diff --git a/tests/VmsPublisherClientSample/AndroidManifest.xml b/tests/VmsPublisherClientSample/AndroidManifest.xml
index d3ac195..fdc1a31 100644
--- a/tests/VmsPublisherClientSample/AndroidManifest.xml
+++ b/tests/VmsPublisherClientSample/AndroidManifest.xml
@@ -15,8 +15,11 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.google.android.car.vms.publisher"
- android:sharedUserId="android.uid.system">
+ package="com.google.android.car.vms.publisher">
+
+ <uses-permission android:name="android.car.permission.VMS_PUBLISHER" />
+ <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
+ <uses-permission android:name="android.permission.CAMERA"/>
<uses-sdk android:minSdkVersion="25" android:targetSdkVersion='25'/>
@@ -24,7 +27,8 @@
android:icon="@mipmap/ic_launcher"
android:directBootAware="true">
<service android:name=".VmsPublisherClientSampleService"
- android:exported="false">
+ android:exported="true"
+ android:singleUser="true">
</service>
</application>
</manifest>
diff --git a/tests/VmsPublisherClientSample/src/com/google/android/car/vms/publisher/VmsPublisherClientSampleService.java b/tests/VmsPublisherClientSample/src/com/google/android/car/vms/publisher/VmsPublisherClientSampleService.java
index c310464..08d37cd 100644
--- a/tests/VmsPublisherClientSample/src/com/google/android/car/vms/publisher/VmsPublisherClientSampleService.java
+++ b/tests/VmsPublisherClientSample/src/com/google/android/car/vms/publisher/VmsPublisherClientSampleService.java
@@ -22,7 +22,6 @@
import android.os.Handler;
import android.os.Message;
-import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
/**
@@ -31,7 +30,7 @@
*/
public class VmsPublisherClientSampleService extends VmsPublisherClientService {
public static final int PUBLISH_EVENT = 0;
- public static final VmsLayer TEST_LAYER = new VmsLayer(0,0);
+ public static final VmsLayer TEST_LAYER = new VmsLayer(0, 0);
private byte mCounter = 0;
private AtomicBoolean mInitialized = new AtomicBoolean(false);
@@ -39,7 +38,7 @@
private final Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
- if (msg.what == PUBLISH_EVENT) {
+ if (msg.what == PUBLISH_EVENT && mInitialized.get()) {
periodicPublish();
}
}
@@ -51,6 +50,8 @@
*/
@Override
public void onVmsPublisherServiceReady() {
+ VmsSubscriptionState subscriptionState = getSubscriptions();
+ onVmsSubscriptionChange(subscriptionState);
}
@Override
@@ -64,6 +65,13 @@
}
}
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ mInitialized.set(false);
+ mHandler.removeMessages(PUBLISH_EVENT);
+ }
+
private void periodicPublish() {
publish(TEST_LAYER, new byte[]{mCounter});
++mCounter;
diff --git a/tests/carservice_test/src/com/android/car/test/VmsPublisherPermissionsTest.java b/tests/carservice_test/src/com/android/car/test/VmsPublisherPermissionsTest.java
new file mode 100644
index 0000000..739f5d0
--- /dev/null
+++ b/tests/carservice_test/src/com/android/car/test/VmsPublisherPermissionsTest.java
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2017 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.test;
+
+import android.annotation.ArrayRes;
+import android.car.VehicleAreaType;
+import android.car.annotation.FutureFeature;
+import android.content.Context;
+import android.content.ContextWrapper;
+import android.content.pm.PackageManager;
+import android.content.res.Resources;
+import android.hardware.automotive.vehicle.V2_0.VehiclePropValue;
+import android.hardware.automotive.vehicle.V2_0.VehiclePropertyAccess;
+import android.hardware.automotive.vehicle.V2_0.VehiclePropertyChangeMode;
+import android.hardware.automotive.vehicle.V2_1.VehicleProperty;
+import android.hardware.automotive.vehicle.V2_1.VmsBaseMessageIntegerValuesIndex;
+import android.hardware.automotive.vehicle.V2_1.VmsMessageType;
+
+import com.android.car.R;
+import com.android.car.vehiclehal.VehiclePropValueBuilder;
+import com.android.car.vehiclehal.test.MockedVehicleHal;
+import com.android.car.vehiclehal.test.MockedVehicleHal.VehicleHalPropertyHandler;
+
+import java.util.ArrayList;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+
+@FutureFeature
+public class VmsPublisherPermissionsTest extends MockedCarTestBase {
+ private static final String TAG = "VmsPublisherTest";
+ private static final int MOCK_PUBLISHER_LAYER_ID = 0;
+ private static final int MOCK_PUBLISHER_LAYER_VERSION = 0;
+
+ private HalHandler mHalHandler;
+ // Used to block until the HAL property is updated in HalHandler.onPropertySet.
+ private Semaphore mHalHandlerSemaphore;
+
+ @Override
+ protected synchronized void configureMockedHal() {
+ mHalHandler = new HalHandler();
+ addProperty(VehicleProperty.VEHICLE_MAP_SERVICE, mHalHandler)
+ .setChangeMode(VehiclePropertyChangeMode.ON_CHANGE)
+ .setAccess(VehiclePropertyAccess.READ_WRITE)
+ .setSupportedAreas(VehicleAreaType.VEHICLE_AREA_TYPE_NONE);
+ }
+
+ /**
+ * Creates a context with the resource vmsPublisherClients overridden. The overridden value
+ * contains the name of the test service defined also in this test package.
+ */
+ @Override
+ protected Context getCarServiceContext() throws PackageManager.NameNotFoundException {
+ Context context = getContext()
+ .createPackageContext("com.android.car", Context.CONTEXT_IGNORE_SECURITY);
+ Resources resources = new Resources(context.getAssets(),
+ context.getResources().getDisplayMetrics(),
+ context.getResources().getConfiguration()) {
+ @Override
+ public String[] getStringArray(@ArrayRes int id) throws NotFoundException {
+ if (id == R.array.vmsPublisherClients) {
+ return new String[]{
+ "com.google.android.car.vms.publisher/"
+ + ".VmsPublisherClientSampleService"};
+ } else if (id == R.array.vmsSafePermissions) {
+ return new String[]{"android.permission.ACCESS_FINE_LOCATION"};
+ }
+ return super.getStringArray(id);
+ }
+ };
+ ContextWrapper wrapper = new ContextWrapper(context) {
+ @Override
+ public Resources getResources() {
+ return resources;
+ }
+ };
+ return wrapper;
+ }
+
+ private VehiclePropValue getHalSubscriptionRequest() {
+ return VehiclePropValueBuilder.newBuilder(VehicleProperty.VEHICLE_MAP_SERVICE)
+ .addIntValue(VmsMessageType.SUBSCRIBE)
+ .addIntValue(MOCK_PUBLISHER_LAYER_ID)
+ .addIntValue(MOCK_PUBLISHER_LAYER_VERSION)
+ .build();
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ if (!VmsTestUtils.canRunTest(TAG)) return;
+ /**
+ * First init the semaphore, setUp will start a series of events that will ultimately
+ * update the HAL layer and release this semaphore.
+ */
+ mHalHandlerSemaphore = new Semaphore(0);
+ super.setUp();
+
+ // Inject a subscribe event which simulates the HAL is subscribed to the Sample Publisher.
+ MockedVehicleHal mHal = getMockedVehicleHal();
+ mHal.injectEvent(getHalSubscriptionRequest());
+ }
+
+ @Override
+ protected synchronized void tearDown() throws Exception {
+ if (!VmsTestUtils.canRunTest(TAG)) return;
+ super.tearDown();
+ }
+
+ /**
+ * The method setUp initializes all the Car services, including the VmsPublisherService.
+ * The VmsPublisherService will start and configure its list of clients. This list was
+ * overridden in the method getCarServiceContext.
+ * Therefore, only VmsPublisherClientSampleService will be started.
+ * The service VmsPublisherClientSampleService will publish one message, which is validated in
+ * this test.
+ */
+ public void testPermissions() throws Exception {
+ if (!VmsTestUtils.canRunTest(TAG)) return;
+ assertTrue(mHalHandlerSemaphore.tryAcquire(2L, TimeUnit.SECONDS));
+ // At this point the client initialization finished. Let's validate the permissions.
+ // The VMS service is only allowed to grant ACCESS_FINE_LOCATION but not CAMERA.
+ assertTrue(
+ getContext().getPackageManager().checkPermission(
+ "android.permission.ACCESS_FINE_LOCATION",
+ "com.google.android.car.vms.publisher")
+ == PackageManager.PERMISSION_GRANTED);
+ assertFalse(getContext().getPackageManager().checkPermission(
+ "android.permission.CAMERA", "com.google.android.car.vms.publisher")
+ == PackageManager.PERMISSION_GRANTED);
+ }
+
+ private class HalHandler implements VehicleHalPropertyHandler {
+ @Override
+ public synchronized void onPropertySet(VehiclePropValue value) {
+ // If this is the data message release the semaphore so the test can continue.
+ ArrayList<Integer> int32Values = value.value.int32Values;
+ if (int32Values.get(VmsBaseMessageIntegerValuesIndex.VMS_MESSAGE_TYPE) ==
+ VmsMessageType.DATA) {
+ mHalHandlerSemaphore.release();
+ }
+ }
+ }
+}
diff --git a/tools/bootanalyze/bootanalyze.py b/tools/bootanalyze/bootanalyze.py
index e50627a..4b814c7 100755
--- a/tools/bootanalyze/bootanalyze.py
+++ b/tools/bootanalyze/bootanalyze.py
@@ -48,6 +48,7 @@
ADB_CMD = "adb"
TIMING_THRESHOLD = 5.0
BOOT_PROP = "\[ro\.boottime\.([^\]]+)\]:\s+\[(\d+)\]"
+BOOTLOADER_TIME_PROP = "\[ro\.boot\.boottime\]:\s+\[([^\]]+)\]"
max_wait_time = BOOT_TIME_TOO_BIG
@@ -278,7 +279,7 @@
if not logcat_event_time.get(KERNEL_TIME_KEY):
print "kernel time not captured in logcat, cannot get time diff"
- return None, None, None
+ return None, None, None, None
diffs = []
diffs.append((logcat_event_time[KERNEL_TIME_KEY], logcat_event_time[KERNEL_TIME_KEY]))
if logcat_event_time.get(BOOT_ANIM_END_TIME_KEY) and dmesg_event_time.get(BOOT_ANIM_END_TIME_KEY):
@@ -288,7 +289,7 @@
if not dmesg_event_time.get(KERNEL_BOOT_COMPLETE):
print "BootAnimEnd time or BootComplete-kernel not captured in both log" +\
", cannot get time diff"
- return None, None, None
+ return None, None, None, None
diffs.append((logcat_event_time[KERNEL_BOOT_COMPLETE],\
logcat_event_time[KERNEL_BOOT_COMPLETE] - dmesg_event_time[KERNEL_BOOT_COMPLETE]))
@@ -316,7 +317,7 @@
else:
events[k] = 0.0
- data_points = {}
+ data_points = collections.OrderedDict()
print "-----------------"
print "ro.boottime.*: time"
@@ -337,9 +338,24 @@
'from_dmesg': item[0] in replaced_from_dmesg,
'logcat_value': logcat_original_time[item[0]]
}
+ # add times with bootloader
+ if events.get("BootComplete") and boottime_events.get("bootloader"):
+ total = events["BootComplete"] + boottime_events["bootloader"]
+ data_points["*BootComplete+Bootloader"] = {
+ 'value': total,
+ 'from_dmesg': False,
+ 'logcat_value': 0.0
+ }
+ if events.get("LauncherStart") and boottime_events.get("bootloader"):
+ total = events["LauncherStart"] + boottime_events["bootloader"]
+ data_points["*LauncherStart+Bootloader"] = {
+ 'value': total,
+ 'from_dmesg': False,
+ 'logcat_value': 0.0
+ }
+ for k, v in data_points.iteritems():
print '{0:30}: {1:<7.5} {2:1} ({3})'.format(
- item[0], item[1], '*' if item[0] in replaced_from_dmesg else '',
- logcat_original_time[item[0]])
+ k, v['value'], '*' if v['from_dmesg'] else '', v['logcat_value'])
print '\n* - event time was obtained from dmesg log\n'
@@ -520,6 +536,8 @@
stdout=subprocess.PIPE);
out = process.stdout
pattern = re.compile(BOOT_PROP)
+ pattern_bootloader = re.compile(BOOTLOADER_TIME_PROP)
+ bootloader_time = 0.0
for line in out:
match = pattern.match(line)
if match:
@@ -527,7 +545,18 @@
events[match.group(1)] = float(match.group(2)) / 1000.0 #ms to s
else:
events[match.group(1)] = float(match.group(2)) / 1000000000.0 #ns to s
+ match = pattern_bootloader.match(line)
+ if match:
+ items = match.group(1).split(",")
+ for item in items:
+ entry_pair = item.split(":")
+ entry_name = entry_pair[0]
+ time_spent = float(entry_pair[1]) / 1000 #ms to s
+ if entry_name != "SW":
+ bootloader_time = bootloader_time + time_spent
ordered_event = collections.OrderedDict()
+ if bootloader_time != 0.0:
+ ordered_event["bootloader"] = bootloader_time;
for item in sorted(events.items(), key=operator.itemgetter(1)):
ordered_event[item[0]] = item[1]
return ordered_event
diff --git a/tools/bootanalyze/config.yaml b/tools/bootanalyze/config.yaml
index 46b2d21..923ca5d 100644
--- a/tools/bootanalyze/config.yaml
+++ b/tools/bootanalyze/config.yaml
@@ -50,6 +50,6 @@
KeyguardShown: KeyguardServiceDelegate.*\*\*\*\* SHOWN CALLED \*\*\*\*
BootComplete: Starting phase 1000
BootComplete_kernel: processing action \(sys\.boot_completed=1\)
- LauncherStart: START.*HOME.*(NexusLauncherActivity|GEL|LensPickerTrampolineActivity)
+ LauncherStart: START.*HOME.*(NexusLauncherActivity|GEL|LensPickerTrampolineActivity|SetupWizardActivity)
FsStat: fs_stat, partition:userdata stat:(0x\S+)