aboutsummaryrefslogtreecommitdiff
path: root/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/cluster
diff options
context:
space:
mode:
authorPavel Maltsev <pavelm@google.com>2017-07-16 19:48:57 -0700
committerPavel Maltsev <pavelm@google.com>2017-07-19 19:23:12 -0700
commit905968cf95d4c8608d6d9351b5dd10fe994a1220 (patch)
treea05c210fae4e5139f12ce852d7066e17fd2abc32 /tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/cluster
parent909546fc1aea53bb86fb1a91d11a11bd2cd4befd (diff)
downloadCar-905968cf95d4c8608d6d9351b5dd10fe994a1220.tar.gz
Allow activities in instrument cluster
- Added new CarInstrumentClusterManager to start activity in the cluster and subscribe to cluster specific events - Cluster vendor implementation (InstrumentClusterRenderingService) was extended, now it can notify Car Service with ActivityOptions that holds info how to launch activity in the cluster for specific category, also it can send additional info such as unobscured bounds (ClusterActivityState) - added DirectRenderingClusterSample which is an example of vendor implementation that utilizes new features - added FakeClusterNavigationActivity in Kitchensink which is a dummy nav activity that can be run in the cluster, it has appropriate permissions and activity category in manifest Test: kitchensink Bug: b/37500371 Change-Id: Ic4b3709a3b7e1310dbd1c499990eea64479b3333
Diffstat (limited to 'tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/cluster')
-rw-r--r--tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/cluster/FakeClusterNavigationActivity.java103
-rw-r--r--tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/cluster/InstrumentClusterFragment.java113
2 files changed, 189 insertions, 27 deletions
diff --git a/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/cluster/FakeClusterNavigationActivity.java b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/cluster/FakeClusterNavigationActivity.java
new file mode 100644
index 0000000000..964d8128ee
--- /dev/null
+++ b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/cluster/FakeClusterNavigationActivity.java
@@ -0,0 +1,103 @@
+/*
+ * 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.google.android.car.kitchensink.cluster;
+
+import android.app.Activity;
+import android.car.cluster.CarInstrumentClusterManager;
+import android.car.cluster.ClusterActivityState;
+import android.graphics.Rect;
+import android.os.Bundle;
+import android.support.car.Car;
+import android.support.car.CarConnectionCallback;
+import android.support.car.CarNotConnectedException;
+import android.util.Log;
+import android.widget.ImageView;
+import android.widget.RelativeLayout;
+
+import com.google.android.car.kitchensink.R;
+
+/**
+ * Fake navigation activity for instrument cluster.
+ */
+public class FakeClusterNavigationActivity
+ extends Activity
+ implements CarInstrumentClusterManager.Callback {
+
+ private final static String TAG = FakeClusterNavigationActivity.class.getSimpleName();
+
+ private Car mCarApi;
+ private CarInstrumentClusterManager mClusterManager;
+ private ImageView mUnobscuredArea;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ Log.i(TAG, "onCreate");
+ setContentView(R.layout.fake_cluster_navigation_activity);
+ mUnobscuredArea = findViewById(R.id.unobscuredArea);
+
+ mCarApi = Car.createCar(this /* context */, new CarConnectionCallback() {
+
+ @Override
+ public void onConnected(Car car) {
+ onCarConnected(car);
+ }
+
+ @Override
+ public void onDisconnected(Car car) {
+ onCarDisconnected(car);
+ }
+ });
+ Log.i(TAG, "Connecting to car api...");
+ mCarApi.connect();
+ }
+
+
+ @Override
+ public void onClusterActivityStateChanged(String category, Bundle clusterActivityState) {
+ ClusterActivityState state = ClusterActivityState.fromBundle(clusterActivityState);
+ Log.i(TAG, "onClusterActivityStateChanged, category: " + category + ", state: " + state);
+
+ Rect unobscured = state.getUnobscuredBounds();
+ RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(
+ unobscured.width(), unobscured.height());
+ lp.setMargins(unobscured.left, unobscured.top, 0, 0);
+ mUnobscuredArea.setLayoutParams(lp);
+ }
+
+ private void onCarConnected(Car car) {
+ Log.i(TAG, "onCarConnected, car: " + car);
+ try {
+ mClusterManager = (CarInstrumentClusterManager) car.getCarManager(
+ android.car.Car.CAR_INSTRUMENT_CLUSTER_SERVICE);
+ } catch (CarNotConnectedException e) {
+ throw new IllegalStateException(e);
+ }
+
+ try {
+ Log.i(TAG, "registering callback...");
+ mClusterManager.registerCallback(CarInstrumentClusterManager.CATEGORY_NAVIGATION, this);
+ Log.i(TAG, "callback registered");
+ } catch (android.car.CarNotConnectedException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ private void onCarDisconnected(Car car) {
+
+ }
+} \ No newline at end of file
diff --git a/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/cluster/InstrumentClusterFragment.java b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/cluster/InstrumentClusterFragment.java
index 28e0a5d3e7..cfae45f775 100644
--- a/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/cluster/InstrumentClusterFragment.java
+++ b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/cluster/InstrumentClusterFragment.java
@@ -16,18 +16,22 @@
package com.google.android.car.kitchensink.cluster;
import android.app.AlertDialog;
+import android.car.cluster.CarInstrumentClusterManager;
+import android.content.Intent;
+import android.content.pm.PackageManager;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.car.Car;
import android.support.car.CarAppFocusManager;
-import android.support.car.CarNotConnectedException;
import android.support.car.CarConnectionCallback;
+import android.support.car.CarNotConnectedException;
import android.support.car.navigation.CarNavigationStatusManager;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
+import android.widget.Toast;
import com.google.android.car.kitchensink.R;
@@ -37,30 +41,30 @@ import com.google.android.car.kitchensink.R;
public class InstrumentClusterFragment extends Fragment {
private static final String TAG = InstrumentClusterFragment.class.getSimpleName();
+ private static final int DISPLAY_IN_CLUSTER_PERMISSION_REQUEST = 1;
+
private CarNavigationStatusManager mCarNavigationStatusManager;
private CarAppFocusManager mCarAppFocusManager;
private Car mCarApi;
- private final CarConnectionCallback mCarConnectionCallback =
- new CarConnectionCallback() {
- @Override
- public void onConnected(Car car) {
- Log.d(TAG, "Connected to Car Service");
- try {
- mCarNavigationStatusManager = (CarNavigationStatusManager) mCarApi.getCarManager(
- android.car.Car.CAR_NAVIGATION_SERVICE);
- mCarAppFocusManager =
- (CarAppFocusManager) mCarApi.getCarManager(Car.APP_FOCUS_SERVICE);
- } catch (CarNotConnectedException e) {
- Log.e(TAG, "Car is not connected!", e);
- }
+ private final CarConnectionCallback mCarConnectionCallback = new CarConnectionCallback() {
+ @Override
+ public void onConnected(Car car) {
+ Log.d(TAG, "Connected to Car Service");
+ try {
+ mCarNavigationStatusManager =
+ mCarApi.getCarManager(CarNavigationStatusManager.class);
+ mCarAppFocusManager = mCarApi.getCarManager(CarAppFocusManager.class);
+ } catch (CarNotConnectedException e) {
+ Log.e(TAG, "Car is not connected!", e);
}
+ }
- @Override
- public void onDisconnected(Car car) {
- Log.d(TAG, "Disconnect from Car Service");
- }
- };
+ @Override
+ public void onDisconnected(Car car) {
+ Log.d(TAG, "Disconnect from Car Service");
+ }
+ };
private void initCarApi() {
if (mCarApi != null && mCarApi.isConnected()) {
@@ -80,6 +84,7 @@ public class InstrumentClusterFragment extends Fragment {
view.findViewById(R.id.cluster_start_button).setOnClickListener(v -> initCluster());
view.findViewById(R.id.cluster_turn_left_button).setOnClickListener(v -> turnLeft());
+ view.findViewById(R.id.cluster_start_activity).setOnClickListener(v -> startNavActivity());
return view;
}
@@ -91,6 +96,31 @@ public class InstrumentClusterFragment extends Fragment {
super.onCreate(savedInstanceState);
}
+ private void startNavActivity() {
+ CarInstrumentClusterManager clusterManager;
+ try {
+ clusterManager = (CarInstrumentClusterManager) mCarApi.getCarManager(
+ android.car.Car.CAR_INSTRUMENT_CLUSTER_SERVICE);
+ } catch (CarNotConnectedException e) {
+ Log.e(TAG, "Failed to get CarInstrumentClusterManager", e);
+ Toast.makeText(getContext(), "Failed to get CarInstrumentClusterManager",
+ Toast.LENGTH_LONG).show();
+ return;
+ }
+
+ // Implicit intent
+ Intent intent = new Intent(Intent.ACTION_MAIN);
+ intent.addCategory(CarInstrumentClusterManager.CATEGORY_NAVIGATION);
+ try {
+ clusterManager.startActivity(intent);
+ } catch (android.car.CarNotConnectedException e) {
+ Log.e(TAG, "Failed to startActivity in cluster", e);
+ Toast.makeText(getContext(), "Failed to start activity in cluster",
+ Toast.LENGTH_LONG).show();
+ return;
+ }
+ }
+
private void turnLeft() {
try {
mCarNavigationStatusManager
@@ -100,18 +130,20 @@ public class InstrumentClusterFragment extends Fragment {
CarNavigationStatusManager.DISTANCE_METERS);
} catch (CarNotConnectedException e) {
e.printStackTrace();
- initCarApi(); // This might happen due to inst cluster renderer crash.
}
}
private void initCluster() {
try {
- mCarAppFocusManager.addFocusListener(new CarAppFocusManager.OnAppFocusChangedListener() {
- @Override
- public void onAppFocusChanged(CarAppFocusManager manager, int appType, boolean active) {
- Log.d(TAG, "onAppFocusChanged, appType: " + appType + " active: " + active);
- }
- }, CarAppFocusManager.APP_FOCUS_TYPE_NAVIGATION);
+ mCarAppFocusManager
+ .addFocusListener(new CarAppFocusManager.OnAppFocusChangedListener() {
+ @Override
+ public void onAppFocusChanged(CarAppFocusManager manager, int appType,
+ boolean active) {
+ Log.d(TAG, "onAppFocusChanged, appType: " + appType + " active: "
+ + active);
+ }
+ }, CarAppFocusManager.APP_FOCUS_TYPE_NAVIGATION);
} catch (CarNotConnectedException e) {
Log.e(TAG, "Failed to register focus listener", e);
}
@@ -126,6 +158,7 @@ public class InstrumentClusterFragment extends Fragment {
.setMessage(R.string.cluster_nav_app_context_loss)
.show();
}
+
@Override
public void onAppFocusOwnershipGranted(CarAppFocusManager manager, int focus) {
Log.w(TAG, "onAppFocusOwnershipGranted, focus: " + focus);
@@ -155,7 +188,33 @@ public class InstrumentClusterFragment extends Fragment {
.sendNavigationStatus(CarNavigationStatusManager.STATUS_ACTIVE);
} catch (CarNotConnectedException e) {
Log.e(TAG, "Failed to set navigation status, reconnecting to the car", e);
- initCarApi(); // This might happen due to inst cluster renderer crash.
+ }
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ Log.i(TAG, "onResume!");
+ if (getActivity().checkSelfPermission(android.car.Car.PERMISSION_CAR_DISPLAY_IN_CLUSTER)
+ != PackageManager.PERMISSION_GRANTED) {
+ Log.i(TAG, "Requesting: " + android.car.Car.PERMISSION_CAR_DISPLAY_IN_CLUSTER);
+
+ requestPermissions(new String[] {android.car.Car.PERMISSION_CAR_DISPLAY_IN_CLUSTER},
+ DISPLAY_IN_CLUSTER_PERMISSION_REQUEST);
+ } else {
+ Log.i(TAG, "All required permissions granted");
+ }
+ }
+
+ @Override
+ public void onRequestPermissionsResult(int requestCode, String[] permissions,
+ int[] grantResults) {
+ if (DISPLAY_IN_CLUSTER_PERMISSION_REQUEST == requestCode) {
+ for (int i = 0; i < permissions.length; i++) {
+ boolean granted = grantResults[i] == PackageManager.PERMISSION_GRANTED;
+ Log.i(TAG, "onRequestPermissionsResult, requestCode: " + requestCode
+ + ", permission: " + permissions[i] + ", granted: " + granted);
+ }
}
}
}