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
diff --git a/car-lib/src/android/car/cluster/ClusterActivityState.java b/car-lib/src/android/car/cluster/ClusterActivityState.java
new file mode 100644
index 0000000..9a6223c
--- /dev/null
+++ b/car-lib/src/android/car/cluster/ClusterActivityState.java
@@ -0,0 +1,91 @@
+/*
+ * 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 android.car.cluster;
+
+import android.annotation.Nullable;
+import android.graphics.Rect;
+import android.os.Bundle;
+
+/**
+ * Helper class that represents activity state in the cluster and can be serialized / deserialized
+ * to/from bundle.
+ * @hide
+ */
+public class ClusterActivityState {
+    private static final String KEY_VISIBLE = "android.car:activityState.visible";
+    private static final String KEY_UNOBSCURED_BOUNDS = "android.car:activityState.unobscured";
+    private static final String KEY_EXTRAS = "android.car:activityState.extras";
+
+    private boolean mVisible = true;
+    private Rect mUnobscuredBounds;
+    private Bundle mExtras;
+
+    public boolean isVisible() {
+        return mVisible;
+    }
+
+    @Nullable public Rect getUnobscuredBounds() {
+        return mUnobscuredBounds;
+    }
+
+    public ClusterActivityState setVisible(boolean visible) {
+        mVisible = visible;
+        return this;
+    }
+
+    public ClusterActivityState setUnobscuredBounds(Rect unobscuredBounds) {
+        mUnobscuredBounds = unobscuredBounds;
+        return this;
+    }
+
+    public ClusterActivityState setExtras(Bundle bundle) {
+        mExtras = bundle;
+        return this;
+    }
+
+    /** Use factory methods instead. */
+    private ClusterActivityState() {}
+
+    public static ClusterActivityState create(boolean visible, Rect unobscuredBounds) {
+        return new ClusterActivityState()
+                .setVisible(visible)
+                .setUnobscuredBounds(unobscuredBounds);
+    }
+
+    public static ClusterActivityState fromBundle(Bundle bundle) {
+        return new ClusterActivityState()
+                .setVisible(bundle.getBoolean(KEY_VISIBLE, true))
+                .setUnobscuredBounds((Rect) bundle.getParcelable(KEY_UNOBSCURED_BOUNDS))
+                .setExtras(bundle.getBundle(KEY_EXTRAS));
+    }
+
+    public Bundle toBundle() {
+        Bundle b = new Bundle();
+        b.putBoolean(KEY_VISIBLE, mVisible);
+        b.putParcelable(KEY_UNOBSCURED_BOUNDS, mUnobscuredBounds);
+        b.putBundle(KEY_EXTRAS, mExtras);
+        return b;
+    }
+
+    @Override
+    public String toString() {
+        return this.getClass().getSimpleName() + " {"
+                + "visible: " + mVisible + ", "
+                + "unobscuredBounds: " + mUnobscuredBounds
+                + " }";
+    }
+}