adas location bypass test app
Test: manually.
Bug: 191180940
Change-Id: I0aa9126bed0cd00aba10bfd41049f87296f6f4b6
diff --git a/car_product/build/car.mk b/car_product/build/car.mk
index df09aae..5b99320 100644
--- a/car_product/build/car.mk
+++ b/car_product/build/car.mk
@@ -45,6 +45,7 @@
BugReportApp \
NetworkPreferenceApp \
SampleCustomInputService \
+ AdasLocationTestApp \
# SEPolicy for test apps / services
BOARD_SEPOLICY_DIRS += packages/services/Car/car_product/sepolicy/test
diff --git a/tests/AdasLocationTestApp/Android.bp b/tests/AdasLocationTestApp/Android.bp
new file mode 100644
index 0000000..cc52ec7
--- /dev/null
+++ b/tests/AdasLocationTestApp/Android.bp
@@ -0,0 +1,51 @@
+// Copyright (C) 2021 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_app {
+ name: "AdasLocationTestApp",
+
+ srcs: ["src/**/*.java"],
+
+ resource_dirs: ["res"],
+
+ platform_apis: true,
+
+ optimize: {
+ enabled: false,
+ },
+
+ enforce_uses_libs: false,
+ dex_preopt: {
+ enabled: false,
+ },
+
+ required: ["allowed_privapp_com.google.android.car.adaslocation"],
+
+ privileged: true,
+
+ certificate: "platform",
+
+ static_libs: [
+ "com.google.android.material_material",
+ "androidx.appcompat_appcompat",
+ ],
+
+ libs: ["android.car"],
+}
\ No newline at end of file
diff --git a/tests/AdasLocationTestApp/AndroidManifest.xml b/tests/AdasLocationTestApp/AndroidManifest.xml
new file mode 100644
index 0000000..6dcd183
--- /dev/null
+++ b/tests/AdasLocationTestApp/AndroidManifest.xml
@@ -0,0 +1,37 @@
+<!--
+ ~ Copyright (C) 2021 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.google.android.car.adaslocation"
+ android:sharedUserId="android.uid.system">
+
+ <!-- The app needs to access device location to verify ADAS and main location switch work as
+ expected. -->
+ <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
+ <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
+ <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS"/>
+
+ <application android:label="AdasLocationTestApp">
+ <activity android:name=".AdasLocationActivity"
+ android:theme="@style/Theme.AppCompat"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="android.intent.category.LAUNCHER"/>
+ </intent-filter>
+ </activity>
+ </application>
+</manifest>
\ No newline at end of file
diff --git a/tests/AdasLocationTestApp/res/layout/main_activity.xml b/tests/AdasLocationTestApp/res/layout/main_activity.xml
new file mode 100644
index 0000000..0173cd6
--- /dev/null
+++ b/tests/AdasLocationTestApp/res/layout/main_activity.xml
@@ -0,0 +1,102 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2021 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.
+ -->
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:layout_width="fill_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical">
+ <TextView
+ android:id="@+id/main_location_enabled"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_centerHorizontal="true"
+ android:layout_marginTop="100dp"
+ android:textStyle="bold"
+ android:text="main location enabled: "/>
+ <TextView
+ android:id="@+id/main_location_status"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_toRightOf="@id/main_location_enabled"
+ android:layout_marginTop="100dp"
+ android:textStyle="bold"/>
+ <TextView
+ android:id="@+id/adas_location_enabled"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_centerHorizontal="true"
+ android:layout_below="@id/main_location_enabled"
+ android:textStyle="bold"
+ android:text="adas location enabled: "/>
+ <TextView
+ android:id="@+id/adas_location_status"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/main_location_status"
+ android:layout_toRightOf="@id/adas_location_enabled"
+ android:textStyle="bold"/>
+ <TextView
+ android:id="@+id/current_location"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/current_location"
+ android:layout_alignParentLeft="true"
+ android:layout_marginLeft="350dp"
+ android:layout_marginTop= "200dp"
+ android:textStyle="bold"/>
+ <TextView
+ android:id="@+id/current_location_result"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/current_location"
+ android:layout_alignParentLeft="true"
+ android:layout_marginLeft="350dp"
+ android:textStyle="bold"/>
+ <com.google.android.material.floatingactionbutton.FloatingActionButton
+ android:id="@+id/observe_fab"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/current_location_result"
+ android:layout_alignParentLeft="true"
+ app:useCompatPadding="true"
+ android:layout_marginLeft="350dp"/>
+ <TextView
+ android:id="@+id/last_location"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/last_location"
+ android:layout_alignParentRight="true"
+ android:layout_marginRight="350dp"
+ android:layout_marginTop= "200dp"
+ android:textStyle="bold"/>
+ <TextView
+ android:id="@+id/last_location_result"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/last_location"
+ android:layout_alignParentRight="true"
+ android:layout_marginRight="350dp"
+ android:textStyle="bold"/>
+ <com.google.android.material.floatingactionbutton.FloatingActionButton
+ android:id="@+id/query_fab"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/last_location_result"
+ android:layout_alignParentRight="true"
+ app:useCompatPadding="true"
+ android:layout_marginRight="350dp"/>
+</RelativeLayout>
diff --git a/tests/AdasLocationTestApp/res/values/strings.xml b/tests/AdasLocationTestApp/res/values/strings.xml
new file mode 100644
index 0000000..3b97648
--- /dev/null
+++ b/tests/AdasLocationTestApp/res/values/strings.xml
@@ -0,0 +1,21 @@
+<!--
+ ~ Copyright (C) 2021 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.
+ -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="last_location" translatable="false">Last Location</string>
+ <string name="current_location" translatable="false">Current Location</string>
+ <string name="no_last_location" translatable="false">no last location</string>
+ <string name="waiting_for_location" translatable="false">waiting for location</string>
+</resources>
\ No newline at end of file
diff --git a/tests/AdasLocationTestApp/src/com/google/android/car/adaslocation/AdasLocationActivity.java b/tests/AdasLocationTestApp/src/com/google/android/car/adaslocation/AdasLocationActivity.java
new file mode 100644
index 0000000..bcb29f1
--- /dev/null
+++ b/tests/AdasLocationTestApp/src/com/google/android/car/adaslocation/AdasLocationActivity.java
@@ -0,0 +1,195 @@
+/*
+ * Copyright (C) 2021 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.google.android.car.adaslocation;
+
+import android.Manifest;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.PackageManager;
+import android.location.Location;
+import android.location.LocationListener;
+import android.location.LocationManager;
+import android.os.Bundle;
+import android.widget.TextView;
+
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.core.app.ActivityCompat;
+
+import com.google.android.material.floatingactionbutton.FloatingActionButton;
+
+import java.util.Arrays;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+public final class AdasLocationActivity extends AppCompatActivity {
+ private static final int KS_PERMISSIONS_REQUEST = 1;
+
+ private static final String[] REQUIRED_PERMISSIONS = new String[]{
+ Manifest.permission.ACCESS_FINE_LOCATION,
+ Manifest.permission.ACCESS_COARSE_LOCATION,
+ };
+
+ private boolean mIsRegister;
+ private LocationManager mLocationManager;
+ private FloatingActionButton mObserveFab;
+ private TextView mObserveLocationResult;
+ private LocationListener mLocationListener;
+ private FloatingActionButton mQueryFab;
+ private TextView mLastLocationResult;
+ private TextView mMainLocationEnabled;
+ private TextView mAdasLocationEnabled;
+ private BroadcastReceiver mReceiver;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.main_activity);
+
+ mLocationManager = getApplicationContext().getSystemService(LocationManager.class);
+ mObserveFab = findViewById(R.id.observe_fab);
+ mObserveLocationResult = findViewById(R.id.current_location_result);
+ mLocationListener = new LocationListener() {
+ @Override
+ public void onLocationChanged(Location location) {
+ mObserveLocationResult.setText(locationToFormattedString(location));
+ }
+
+ @Override
+ public void onProviderEnabled(String provider) {
+ }
+
+ @Override
+ public void onProviderDisabled(String provider) {
+ }
+ };
+ mObserveFab.setOnClickListener(
+ v -> {
+ if (!mIsRegister) {
+ startListening();
+ } else {
+ stopListening();
+ }
+ }
+ );
+ mQueryFab = findViewById(R.id.query_fab);
+ mLastLocationResult = findViewById(R.id.last_location_result);
+ mQueryFab.setOnClickListener(
+ v -> {
+ Location location = mLocationManager
+ .getLastKnownLocation(LocationManager.GPS_PROVIDER);
+ if (location != null) {
+ mLastLocationResult.setText(locationToFormattedString(location));
+ } else {
+ mLastLocationResult.setText(R.string.no_last_location);
+ }
+ }
+ );
+
+ mReceiver =
+ new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (LocationManager.MODE_CHANGED_ACTION == intent.getAction()) {
+ mMainLocationEnabled.setText(Boolean.toString(mLocationManager
+ .isLocationEnabled()));
+ return;
+ }
+ if (LocationManager.ACTION_ADAS_GNSS_ENABLED_CHANGED
+ == intent.getAction()) {
+ mAdasLocationEnabled
+ .setText(Boolean.toString(mLocationManager
+ .isAdasGnssLocationEnabled()));
+ return;
+ }
+ }
+ };
+ }
+
+ @Override
+ public void onStart() {
+ super.onStart();
+ initPermissions();
+
+ mMainLocationEnabled = findViewById(R.id.main_location_status);
+ mMainLocationEnabled.setText(Boolean.toString(mLocationManager.isLocationEnabled()));
+ mAdasLocationEnabled = findViewById(R.id.adas_location_status);
+ mAdasLocationEnabled.setText(Boolean.toString(mLocationManager
+ .isAdasGnssLocationEnabled()));
+
+ IntentFilter intentFilter = new IntentFilter();
+ intentFilter.addAction(LocationManager.MODE_CHANGED_ACTION);
+ intentFilter.addAction(LocationManager.ACTION_ADAS_GNSS_ENABLED_CHANGED);
+ registerReceiver(mReceiver, intentFilter);
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ Set<String> missingPermissions = checkExistingPermissions();
+ if (!missingPermissions.isEmpty()) {
+ return;
+ }
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ if (mIsRegister) {
+ stopListening();
+ }
+ mLastLocationResult.setText("");
+ }
+
+ private static String locationToFormattedString(Location location) {
+ return String.format("Location: lat=%10.6f, lon=%10.6f ",
+ location.getLatitude(),
+ location.getLongitude());
+ }
+
+ private void initPermissions() {
+ Set<String> missingPermissions = checkExistingPermissions();
+ if (!missingPermissions.isEmpty()) {
+ requestPermissions(missingPermissions);
+ }
+ }
+
+ private Set<String> checkExistingPermissions() {
+ return Arrays.stream(REQUIRED_PERMISSIONS).filter(permission -> ActivityCompat
+ .checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED)
+ .collect(Collectors.toSet());
+ }
+
+ private void requestPermissions(Set<String> permissions) {
+ requestPermissions(permissions.toArray(new String[permissions.size()]),
+ KS_PERMISSIONS_REQUEST);
+ }
+
+ private void startListening() {
+ mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,
+ 0, 0, mLocationListener);
+ mObserveLocationResult.setText(R.string.waiting_for_location);
+ mIsRegister = true;
+ }
+
+ private void stopListening() {
+ mLocationManager.removeUpdates(mLocationListener);
+ mObserveLocationResult.setText("");
+ mIsRegister = false;
+ }
+}