aboutsummaryrefslogtreecommitdiff
path: root/car-lib/src/android/car/cluster
diff options
context:
space:
mode:
Diffstat (limited to 'car-lib/src/android/car/cluster')
-rw-r--r--car-lib/src/android/car/cluster/CarInstrumentClusterManager.java7
-rw-r--r--car-lib/src/android/car/cluster/renderer/IInstrumentCluster.aidl2
-rw-r--r--car-lib/src/android/car/cluster/renderer/IInstrumentClusterHelper.aidl49
-rw-r--r--car-lib/src/android/car/cluster/renderer/InstrumentClusterRenderingService.java144
4 files changed, 185 insertions, 17 deletions
diff --git a/car-lib/src/android/car/cluster/CarInstrumentClusterManager.java b/car-lib/src/android/car/cluster/CarInstrumentClusterManager.java
index 54d10e2f1c..2b633a0093 100644
--- a/car-lib/src/android/car/cluster/CarInstrumentClusterManager.java
+++ b/car-lib/src/android/car/cluster/CarInstrumentClusterManager.java
@@ -17,10 +17,10 @@
package android.car.cluster;
import android.annotation.SystemApi;
+import android.car.Car;
import android.car.CarManagerBase;
import android.content.Intent;
import android.os.Bundle;
-import android.os.Handler;
import android.os.IBinder;
/**
@@ -35,7 +35,7 @@ import android.os.IBinder;
*/
@Deprecated
@SystemApi
-public class CarInstrumentClusterManager implements CarManagerBase {
+public class CarInstrumentClusterManager extends CarManagerBase {
/**
* @deprecated use {@link android.car.Car#CATEGORY_NAVIGATION} instead
*
@@ -101,7 +101,8 @@ public class CarInstrumentClusterManager implements CarManagerBase {
}
/** @hide */
- public CarInstrumentClusterManager(IBinder service, Handler handler) {
+ public CarInstrumentClusterManager(Car car, IBinder service) {
+ super(car);
// No-op
}
diff --git a/car-lib/src/android/car/cluster/renderer/IInstrumentCluster.aidl b/car-lib/src/android/car/cluster/renderer/IInstrumentCluster.aidl
index 7deecc747b..4f417961cc 100644
--- a/car-lib/src/android/car/cluster/renderer/IInstrumentCluster.aidl
+++ b/car-lib/src/android/car/cluster/renderer/IInstrumentCluster.aidl
@@ -28,6 +28,8 @@ interface IInstrumentCluster {
/**
* Returns {@link IInstrumentClusterNavigation} that will be passed to the navigation
* application.
+ *
+ * TODO(b/141992448) : remove blocking call
*/
IInstrumentClusterNavigation getNavigationService();
diff --git a/car-lib/src/android/car/cluster/renderer/IInstrumentClusterHelper.aidl b/car-lib/src/android/car/cluster/renderer/IInstrumentClusterHelper.aidl
new file mode 100644
index 0000000000..680e24198e
--- /dev/null
+++ b/car-lib/src/android/car/cluster/renderer/IInstrumentClusterHelper.aidl
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2019 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.renderer;
+
+import android.content.Intent;
+import android.os.Bundle;
+
+/**
+ * Helper binder API for InstrumentClusterRenderingService. This contains binder calls to car
+ * service.
+ *
+ * @hide
+ */
+interface IInstrumentClusterHelper {
+ /**
+ * Start an activity to specified display / user. The activity is considered as
+ * in fixed mode for the display and will be re-launched if the activity crashes, the package
+ * is updated or goes to background for whatever reason.
+ * Only one activity can exist in fixed mode for the target display and calling this multiple
+ * times with different {@code Intent} will lead into making all previous activities into
+ * non-fixed normal state (= will not be re-launched.)
+ *
+ * Do not change binder transaction number.
+ */
+ boolean startFixedActivityModeForDisplayAndUser(in Intent intent,
+ in Bundle activityOptionsBundle, int userId) = 0;
+ /**
+ * The activity lauched on the display is no longer in fixed mode. Re-launching or finishing
+ * should not trigger re-launfhing any more. Note that Activity for non-current user will
+ * be auto-stopped and there is no need to call this for user swiching. Note that this does not
+ * stop the activity but it will not be re-launched any more.
+ *
+ * Do not change binder transaction number.
+ */
+ void stopFixedActivityMode(int displayId) = 1;
+}
diff --git a/car-lib/src/android/car/cluster/renderer/InstrumentClusterRenderingService.java b/car-lib/src/android/car/cluster/renderer/InstrumentClusterRenderingService.java
index 6996119715..ede4b6ad07 100644
--- a/car-lib/src/android/car/cluster/renderer/InstrumentClusterRenderingService.java
+++ b/car-lib/src/android/car/cluster/renderer/InstrumentClusterRenderingService.java
@@ -22,6 +22,7 @@ import android.annotation.MainThread;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
+import android.annotation.UserIdInt;
import android.app.ActivityOptions;
import android.app.Service;
import android.car.Car;
@@ -82,20 +83,35 @@ import java.util.stream.Collectors;
*/
@SystemApi
public abstract class InstrumentClusterRenderingService extends Service {
+ /**
+ * Key to pass IInstrumentClusterHelper binder in onBind call {@link Intent} through extra
+ * {@link Bundle). Both extra bundle and binder itself use this key.
+ *
+ * @hide
+ */
+ public static final String EXTRA_BUNDLE_KEY_FOR_INSTRUMENT_CLUSTER_HELPER =
+ "android.car.cluster.renderer.IInstrumentClusterHelper";
+
private static final String TAG = CarLibLog.TAG_CLUSTER;
private static final String BITMAP_QUERY_WIDTH = "w";
private static final String BITMAP_QUERY_HEIGHT = "h";
+ private static final String BITMAP_QUERY_OFFLANESALPHA = "offLanesAlpha";
+
+ private final Handler mUiHandler = new Handler(Looper.getMainLooper());
private final Object mLock = new Object();
+ // Main thread only
private RendererBinder mRendererBinder;
- private Handler mUiHandler = new Handler(Looper.getMainLooper());
private ActivityOptions mActivityOptions;
private ClusterActivityState mActivityState;
private ComponentName mNavigationComponent;
@GuardedBy("mLock")
private ContextOwner mNavContextOwner;
+ @GuardedBy("mLock")
+ private IInstrumentClusterHelper mInstrumentClusterHelper;
+
private static final int IMAGE_CACHE_SIZE_BYTES = 4 * 1024 * 1024; /* 4 mb */
private final LruCache<String, Bitmap> mCache = new LruCache<String, Bitmap>(
IMAGE_CACHE_SIZE_BYTES) {
@@ -157,6 +173,18 @@ public abstract class InstrumentClusterRenderingService extends Service {
Log.d(TAG, "onBind, intent: " + intent);
}
+ Bundle bundle = intent.getBundleExtra(EXTRA_BUNDLE_KEY_FOR_INSTRUMENT_CLUSTER_HELPER);
+ IBinder binder = null;
+ if (bundle != null) {
+ binder = bundle.getBinder(EXTRA_BUNDLE_KEY_FOR_INSTRUMENT_CLUSTER_HELPER);
+ }
+ if (binder == null) {
+ Log.wtf(TAG, "IInstrumentClusterHelper not passed through binder");
+ } else {
+ synchronized (mLock) {
+ mInstrumentClusterHelper = IInstrumentClusterHelper.Stub.asInterface(binder);
+ }
+ }
if (mRendererBinder == null) {
mRendererBinder = new RendererBinder(getNavigationRenderer());
}
@@ -196,6 +224,76 @@ public abstract class InstrumentClusterRenderingService extends Service {
public void onNavigationComponentReleased() {
}
+ @Nullable
+ private IInstrumentClusterHelper getClusterHelper() {
+ synchronized (mLock) {
+ if (mInstrumentClusterHelper == null) {
+ Log.w("mInstrumentClusterHelper still null, should wait until onBind",
+ new RuntimeException());
+ }
+ return mInstrumentClusterHelper;
+ }
+ }
+
+ /**
+ * Start Activity in fixed mode.
+ *
+ * <p>Activity launched in this way will stay visible across crash, package updatge
+ * or other Activity launch. So this should be carefully used for case like apps running
+ * in instrument cluster.</p>
+ *
+ * <p> Only one Activity can stay in this mode for a display and launching other Activity
+ * with this call means old one get out of the mode. Alternatively
+ * {@link #stopFixedActivityMode(int)} can be called to get the top activitgy out of this
+ * mode.</p>
+ *
+ * @param intent Should include specific {@code ComponentName}.
+ * @param options Should include target display.
+ * @param userId Target user id
+ * @return {@code true} if succeeded. {@code false} may mean the target component is not ready
+ * or available. Note that failure can happen during early boot-up stage even if the
+ * target Activity is in normal state and client should retry when it fails. Once it is
+ * successfully launched, car service will guarantee that it is running across crash or
+ * other events.
+ *
+ * @hide
+ */
+ protected boolean startFixedActivityModeForDisplayAndUser(@NonNull Intent intent,
+ @NonNull ActivityOptions options, @UserIdInt int userId) {
+ IInstrumentClusterHelper helper = getClusterHelper();
+ if (helper == null) {
+ return false;
+ }
+ try {
+ return helper.startFixedActivityModeForDisplayAndUser(intent, options.toBundle(),
+ userId);
+ } catch (RemoteException e) {
+ Log.w("Remote exception from car service", e);
+ // Probably car service will restart and rebind. So do nothing.
+ }
+ return false;
+ }
+
+
+ /**
+ * Stop fixed mode for top Activity in the display. Crashing or launching other Activity
+ * will not re-launch the top Activity any more.
+ *
+ * @hide
+ */
+ protected void stopFixedActivityMode(int displayId) {
+ IInstrumentClusterHelper helper = getClusterHelper();
+ if (helper == null) {
+ return;
+ }
+ try {
+ helper.stopFixedActivityMode(displayId);
+ } catch (RemoteException e) {
+ Log.w("Remote exception from car service, displayId:" + displayId, e);
+ // Probably car service will restart and rebind. So do nothing.
+ }
+ }
+
/**
* Updates the cluster navigation activity by checking which activity to show (an activity of
* the {@link #mNavContextOwner}). If not yet launched, it will do so.
@@ -370,16 +468,19 @@ public abstract class InstrumentClusterRenderingService extends Service {
@CallSuper
@Override
protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
- writer.println("**" + getClass().getSimpleName() + "**");
- writer.println("renderer binder: " + mRendererBinder);
- if (mRendererBinder != null) {
- writer.println("navigation renderer: " + mRendererBinder.mNavigationRenderer);
- }
- writer.println("navigation focus owner: " + getNavigationContextOwner());
- writer.println("activity options: " + mActivityOptions);
- writer.println("activity state: " + mActivityState);
- writer.println("current nav component: " + mNavigationComponent);
- writer.println("current nav packages: " + getNavigationContextOwner().mPackageNames);
+ synchronized (mLock) {
+ writer.println("**" + getClass().getSimpleName() + "**");
+ writer.println("renderer binder: " + mRendererBinder);
+ if (mRendererBinder != null) {
+ writer.println("navigation renderer: " + mRendererBinder.mNavigationRenderer);
+ }
+ writer.println("navigation focus owner: " + getNavigationContextOwner());
+ writer.println("activity options: " + mActivityOptions);
+ writer.println("activity state: " + mActivityState);
+ writer.println("current nav component: " + mNavigationComponent);
+ writer.println("current nav packages: " + getNavigationContextOwner().mPackageNames);
+ writer.println("mInstrumentClusterHelper" + mInstrumentClusterHelper);
+ }
}
private class RendererBinder extends IInstrumentCluster.Stub {
@@ -539,8 +640,18 @@ public abstract class InstrumentClusterRenderingService extends Service {
}
/**
+ * See {@link #getBitmap(Uri, int, int, float)}
+ *
+ * @throws IllegalArgumentException if {@code width} or {@code height} is not greater than 0.
+ */
+ @Nullable
+ public Bitmap getBitmap(Uri uri, int width, int height) {
+ return getBitmap(uri, width, height, 1f);
+ }
+
+ /**
* Fetches a bitmap from the navigation context owner (application holding navigation focus)
- * of the given width and height. The fetched bitmaps are cached.
+ * of the given width and height and off lane opacity. The fetched bitmaps are cached.
* It returns null if:
* <ul>
* <li>there is no navigation context owner
@@ -549,13 +660,17 @@ public abstract class InstrumentClusterRenderingService extends Service {
* </ul>
* This is a costly operation. Returned bitmaps should be fetched on a secondary thread.
*
- * @throws IllegalArgumentException if {@code width} or {@code height} is not greater than 0.
+ * @throws IllegalArgumentException if width, height <= 0, or 0 > offLanesAlpha > 1
+ * @hide
*/
@Nullable
- public Bitmap getBitmap(Uri uri, int width, int height) {
+ public Bitmap getBitmap(Uri uri, int width, int height, float offLanesAlpha) {
if (width <= 0 || height <= 0) {
throw new IllegalArgumentException("Width and height must be > 0");
}
+ if (offLanesAlpha < 0 || offLanesAlpha > 1) {
+ throw new IllegalArgumentException("offLanesAlpha must be between [0, 1]");
+ }
try {
ContextOwner contextOwner = getNavigationContextOwner();
@@ -567,6 +682,7 @@ public abstract class InstrumentClusterRenderingService extends Service {
uri = uri.buildUpon()
.appendQueryParameter(BITMAP_QUERY_WIDTH, String.valueOf(width))
.appendQueryParameter(BITMAP_QUERY_HEIGHT, String.valueOf(height))
+ .appendQueryParameter(BITMAP_QUERY_OFFLANESALPHA, String.valueOf(offLanesAlpha))
.build();
String host = uri.getHost();