[automerger skipped] Merge "Convert sysui to bp" into pi-dev-plus-aosp
am: 1b49835632 -s ours
Change-Id: I6e497f22eea641e5c2be55509e17fe9b17d35b78
diff --git a/car-lib/api/current.txt b/car-lib/api/current.txt
index 57975a2..6744238 100644
--- a/car-lib/api/current.txt
+++ b/car-lib/api/current.txt
@@ -493,9 +493,9 @@
public static final class CarSettings.Global {
ctor public CarSettings.Global();
- field public static final java.lang.String KEY_GARAGE_MODE_ENABLED = "android.car.GARAGE_MODE_ENABLED";
- field public static final java.lang.String KEY_GARAGE_MODE_MAINTENANCE_WINDOW = "android.car.GARAGE_MODE_MAINTENANCE_WINDOW";
- field public static final java.lang.String KEY_GARAGE_MODE_WAKE_UP_TIME = "android.car.GARAGE_MODE_WAKE_UP_TIME";
+ field public static final deprecated java.lang.String KEY_GARAGE_MODE_ENABLED = "android.car.GARAGE_MODE_ENABLED";
+ field public static final deprecated java.lang.String KEY_GARAGE_MODE_MAINTENANCE_WINDOW = "android.car.GARAGE_MODE_MAINTENANCE_WINDOW";
+ field public static final deprecated java.lang.String KEY_GARAGE_MODE_WAKE_UP_TIME = "android.car.GARAGE_MODE_WAKE_UP_TIME";
}
public final class SpeedBumpConfiguration implements android.os.Parcelable {
diff --git a/car-lib/api/system-current.txt b/car-lib/api/system-current.txt
index df6b85e..c4c4385 100644
--- a/car-lib/api/system-current.txt
+++ b/car-lib/api/system-current.txt
@@ -693,7 +693,7 @@
}
public static abstract interface CarPowerManager.CarPowerStateListener {
- method public abstract void onStateChanged(int);
+ method public abstract void onStateChanged(int, java.util.concurrent.CompletableFuture<java.lang.Void>);
field public static final int SHUTDOWN_CANCELLED = 0; // 0x0
field public static final int SHUTDOWN_ENTER = 1; // 0x1
field public static final int SUSPEND_ENTER = 2; // 0x2
diff --git a/car-lib/src/android/car/VehicleHvacFanDirection.java b/car-lib/src/android/car/VehicleHvacFanDirection.java
new file mode 100644
index 0000000..1de111b
--- /dev/null
+++ b/car-lib/src/android/car/VehicleHvacFanDirection.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2018 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;
+
+/**
+ * Bit flags for fan direction.
+ * This constant must be used with HVAC_FAN_DIRECTION property in {@link VehiclePropertyIds}.
+ * @hide
+ */
+public final class VehicleHvacFanDirection {
+ public static final int FACE = 0x1;
+ public static final int FLOOR = 0x2;
+ public static final int DEFROST = 0x4;
+
+ private VehicleHvacFanDirection() {}
+}
diff --git a/car-lib/src/android/car/hardware/CarVendorExtensionManager.java b/car-lib/src/android/car/hardware/CarVendorExtensionManager.java
index 9f06764..5e07ace 100644
--- a/car-lib/src/android/car/hardware/CarVendorExtensionManager.java
+++ b/car-lib/src/android/car/hardware/CarVendorExtensionManager.java
@@ -106,7 +106,6 @@
if (mCallbacks.isEmpty()) {
mListenerToBase = new CarPropertyEventListenerToBase(this);
}
-
List<CarPropertyConfig> configs = mPropertyManager.getPropertyList();
for (CarPropertyConfig c : configs) {
// Register each individual propertyId
diff --git a/car-lib/src/android/car/hardware/cabin/CarCabinManager.java b/car-lib/src/android/car/hardware/cabin/CarCabinManager.java
index 1dee2b0..7d5715f 100644
--- a/car-lib/src/android/car/hardware/cabin/CarCabinManager.java
+++ b/car-lib/src/android/car/hardware/cabin/CarCabinManager.java
@@ -496,8 +496,6 @@
mCarPropertyMgr.registerListener(mListenerToBase, c.getPropertyId(), 0);
}
mCallbacks.add(callback);
-
-
}
/**
@@ -510,7 +508,7 @@
mCallbacks.remove(callback);
List<CarPropertyConfig> configs = getPropertyList();
for (CarPropertyConfig c : configs) {
- // Register each individual propertyId
+ // Register each individual propertyId
mCarPropertyMgr.unregisterListener(mListenerToBase, c.getPropertyId());
}
if (mCallbacks.isEmpty()) {
diff --git a/car-lib/src/android/car/hardware/hvac/CarHvacManager.java b/car-lib/src/android/car/hardware/hvac/CarHvacManager.java
index c953d6f..f86640f 100644
--- a/car-lib/src/android/car/hardware/hvac/CarHvacManager.java
+++ b/car-lib/src/android/car/hardware/hvac/CarHvacManager.java
@@ -54,10 +54,6 @@
* HVAC property IDs for get/set methods
*/
/**
- * Global HVAC properties. There is only a single instance in a car.
- * Global properties are in the range of 0-0x3FFF.
- */
- /**
* Mirror defrosters state, bool type
* true indicates mirror defroster is on
*/
@@ -81,10 +77,6 @@
public static final int ID_TEMPERATURE_DISPLAY_UNITS = 0x1140050e;
/**
- * ID_ZONED_* represents properties available on a per-zone basis. All zones in a car are
- * not required to have the same properties. Zone specific properties start at 0x4000.
- */
- /**
* Temperature setpoint, float type
* Temperature set by the user, units are in degrees Celsius.
*/
@@ -325,7 +317,7 @@
}
List<CarPropertyConfig> configs = getPropertyList();
for (CarPropertyConfig c : configs) {
- // Register each individual propertyId
+ // Register each individual propertyId
mCarPropertyMgr.registerListener(mListenerToBase, c.getPropertyId(), 0);
}
mCallbacks.add(callback);
@@ -343,6 +335,7 @@
for (CarPropertyConfig c : configs) {
// Register each individual propertyId
mCarPropertyMgr.unregisterListener(mListenerToBase, c.getPropertyId());
+
}
} catch (Exception e) {
Log.e(TAG, "getPropertyList exception ", e);
diff --git a/car-lib/src/android/car/hardware/power/CarPowerManager.java b/car-lib/src/android/car/hardware/power/CarPowerManager.java
index 38c5cd1..f04b1c6 100644
--- a/car-lib/src/android/car/hardware/power/CarPowerManager.java
+++ b/car-lib/src/android/car/hardware/power/CarPowerManager.java
@@ -16,15 +16,7 @@
package android.car.hardware.power;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.ref.WeakReference;
-import java.util.concurrent.Executor;
-
-import com.android.internal.annotations.GuardedBy;
-
import android.annotation.IntDef;
-import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.car.Car;
import android.car.CarManagerBase;
@@ -32,10 +24,15 @@
import android.content.Context;
import android.os.Handler;
import android.os.IBinder;
-import android.os.Message;
import android.os.RemoteException;
import android.util.Log;
+import com.android.internal.annotations.GuardedBy;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.concurrent.CompletableFuture;
+
/**
* API for receiving power state change notifications.
* @hide
@@ -46,7 +43,7 @@
private final static String TAG = "CarPowerManager";
private CarPowerStateListener mListener;
private final ICarPower mService;
- private Executor mExecutor;
+ private CompletableFuture<Void> mFuture;
@GuardedBy("mLock")
private ICarPowerStateListener mListenerToService;
@@ -97,32 +94,48 @@
/**
* onStateChanged() states. These definitions must match the ones located in the native
* CarPowerManager: packages/services/Car/car-lib/native/CarPowerManager/CarPowerManager.h
- *
*/
/**
* Shutdown is cancelled, return to normal state.
*/
- public static final int SHUTDOWN_CANCELLED = 0;
+ int SHUTDOWN_CANCELLED = 0;
/**
* Enter shutdown state. Application is expected to cleanup and be ready to shutdown.
*/
- public static final int SHUTDOWN_ENTER = 1;
+ int SHUTDOWN_ENTER = 1;
/**
* Enter suspend state. Application is expected to cleanup and be ready to suspend.
*/
- public static final int SUSPEND_ENTER = 2;
+ int SUSPEND_ENTER = 2;
/**
* Wake up from suspend, or resume from a cancelled suspend. Application transitions to
* normal state.
*/
- public static final int SUSPEND_EXIT = 3;
+ int SUSPEND_EXIT = 3;
+ /**
+ * NonInteractive state
+ * @hide
+ */
+ int NON_INTERACTIVE = 4;
+ /**
+ * Interactive state (Full On State)
+ * @hide
+ */
+ int INTERACTIVE = 5;
+ /**
+ * State where system is getting ready for shutdown or suspend
+ * @hide
+ */
+ int SHUTDOWN_PREPARE = 6;
/**
* Called when power state changes
* @param state New power state of device.
- * @param token Opaque identifier to keep track of listener events.
+ * @param future CompletableFuture used by consumer modules to notify CPMS that
+ * they are ready to continue shutting down. CPMS will wait until this future
+ * is completed.
*/
- void onStateChanged(int state);
+ void onStateChanged(int state, CompletableFuture<Void> future);
}
/**
@@ -169,28 +182,39 @@
}
/**
+ * Schedule next wake up time in CarPowerManagementSystem
+ * @throws CarNotConnectedException
+ * @hide
+ */
+ public void scheduleNextWakeupTime(int seconds) throws CarNotConnectedException {
+ try {
+ mService.scheduleNextWakeupTime(seconds);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Exception while scheduling next wakeup time", e);
+ throw new CarNotConnectedException(e);
+ }
+ }
+
+ /**
* Sets a listener to receive power state changes. Only one listener may be set at a time.
- * Caller may add an Executor to allow the callback to run in a seperate thread of execution
- * if the {@link onStateChanged} method will take some time. If no Executor is passed in,
- * the listener will run in the Binder thread and should finish quickly. After
- * {@link onStateChanged} is called, the {@link finished} method will automatically be called
- * to notify {@link CarPowerManagementService} that the application has handled the
- * {@link #SHUTDOWN_ENTER} or {@link #SUSPEND_ENTER} state transitions. Only these two states
- * require a confirmation from the application.
+ * For calls that require completion before continue, we attach a {@link CompletableFuture}
+ * which is being used as a signal that caller is finished and ready to proceed.
+ * Once future is completed, the {@link finished} method will automatically be called to notify
+ * {@link CarPowerManagementService} that the application has handled the
+ * {@link #SHUTDOWN_PREPARE} state transition.
*
- * @param executor
* @param listener
* @throws CarNotConnectedException, IllegalStateException
* @hide
*/
- public void setListener(CarPowerStateListener listener, Executor executor) throws
+ public void setListener(CarPowerStateListener listener) throws
CarNotConnectedException, IllegalStateException {
synchronized(mLock) {
if (mListenerToService == null) {
ICarPowerStateListener listenerToService = new ICarPowerStateListener.Stub() {
@Override
public void onStateChanged(int state, int token) throws RemoteException {
- handleEvent(state, token);
+ handleStateTransition(state, token);
}
};
try {
@@ -203,9 +227,8 @@
Car.checkCarNotConnectedExceptionFromCarService(ex);
}
}
- if ((mExecutor == null) && (mListener == null)) {
- // Update listener and executor
- mExecutor = executor;
+ if (mListener == null) {
+ // Update listener
mListener = listener;
} else {
throw new IllegalStateException("Listener must be cleared first");
@@ -223,7 +246,7 @@
listenerToService = mListenerToService;
mListenerToService = null;
mListener = null;
- mExecutor = null;
+ cleanupFuture();
}
if (listenerToService == null) {
@@ -241,33 +264,37 @@
}
}
- private void handleEvent(int state, int token) {
- Executor executor;
- synchronized (mLock) {
- executor = mExecutor;
- }
- if (executor != null) {
- executor.execute(() -> {
- handleEventInternal(state, token);
+ private void handleStateTransition(int state, int token) {
+ // Update CompletableFuture. It will recreate it or just clean it up
+ updateFuture(state, token);
+ // Notify user that state has changed and supply future
+ mListener.onStateChanged(state, mFuture);
+ }
+
+ private void updateFuture(int state, int token) {
+ cleanupFuture();
+ if (state == CarPowerStateListener.SHUTDOWN_PREPARE) {
+ mFuture = new CompletableFuture<>();
+ mFuture.whenComplete((result, exception) -> {
+ if (exception != null) {
+ Log.e(TAG, "Exception occurred while waiting for future", exception);
+ return;
+ }
+ try {
+ mService.finished(mListenerToService, token);
+ } catch (RemoteException e) {
+ Log.e(TAG, "RemoteException while calling CPMS.finished()", e);
+ }
});
- } else {
- // If no executor provided, run in binder thread. This should only be done for
- // trivial listener logic.
- handleEventInternal(state, token);
}
}
- private void handleEventInternal(int state, int token) {
- mListener.onStateChanged(state);
- if ((state == CarPowerStateListener.SHUTDOWN_ENTER) ||
- (state == CarPowerStateListener.SUSPEND_ENTER)) {
- // Notify service that state change is complete for SHUTDOWN_ENTER and SUSPEND_ENTER
- // states only.
- try {
- mService.finished(mListenerToService, token);
- } catch (RemoteException e) {
- Log.e(TAG, "Exception in finished", e);
+ private void cleanupFuture() {
+ if (mFuture != null) {
+ if (!mFuture.isDone()) {
+ mFuture.cancel(false);
}
+ mFuture = null;
}
}
diff --git a/car-lib/src/android/car/hardware/power/ICarPower.aidl b/car-lib/src/android/car/hardware/power/ICarPower.aidl
index 851ed0c..95f9ec7 100644
--- a/car-lib/src/android/car/hardware/power/ICarPower.aidl
+++ b/car-lib/src/android/car/hardware/power/ICarPower.aidl
@@ -29,4 +29,6 @@
int getBootReason() = 3;
void finished(in ICarPowerStateListener listener, int token) = 4;
+
+ void scheduleNextWakeupTime(int seconds) = 5;
}
diff --git a/car-lib/src/android/car/media/CarAudioManager.java b/car-lib/src/android/car/media/CarAudioManager.java
index 7257255..2b9e5af 100644
--- a/car-lib/src/android/car/media/CarAudioManager.java
+++ b/car-lib/src/android/car/media/CarAudioManager.java
@@ -116,7 +116,7 @@
try {
return mService.getGroupMaxVolume(groupId);
} catch (RemoteException e) {
- Log.e(CarLibLog.TAG_CAR, "getUsageMaxVolume failed", e);
+ Log.e(CarLibLog.TAG_CAR, "getGroupMaxVolume failed", e);
throw new CarNotConnectedException(e);
}
}
@@ -134,7 +134,7 @@
try {
return mService.getGroupMinVolume(groupId);
} catch (RemoteException e) {
- Log.e(CarLibLog.TAG_CAR, "getUsageMinVolume failed", e);
+ Log.e(CarLibLog.TAG_CAR, "getGroupMinVolume failed", e);
throw new CarNotConnectedException(e);
}
}
@@ -155,7 +155,7 @@
try {
return mService.getGroupVolume(groupId);
} catch (RemoteException e) {
- Log.e(CarLibLog.TAG_CAR, "getUsageVolume failed", e);
+ Log.e(CarLibLog.TAG_CAR, "getGroupVolume failed", e);
throw new CarNotConnectedException(e);
}
}
diff --git a/car-lib/src/android/car/settings/CarSettings.java b/car-lib/src/android/car/settings/CarSettings.java
index f5e1037..abbefc1 100644
--- a/car-lib/src/android/car/settings/CarSettings.java
+++ b/car-lib/src/android/car/settings/CarSettings.java
@@ -32,17 +32,24 @@
*/
public static final class Global {
/**
- * Key for when to wake up to run garage mode.
+ * DEPRECATED. Will be removed in Q. Key for when to wake up to run garage mode.
+ * @deprecated not used by GarageMode anymore. Will be removed in Q.
*/
+ @Deprecated
public static final String KEY_GARAGE_MODE_WAKE_UP_TIME =
"android.car.GARAGE_MODE_WAKE_UP_TIME";
/**
- * Key for whether garage mode is enabled.
+ * DEPRECATED. Will be removed in Q. Key for whether garage mode is enabled.
+ * @deprecated not used by GarageMode anymore. Will be removed in Q.
*/
+ @Deprecated
public static final String KEY_GARAGE_MODE_ENABLED = "android.car.GARAGE_MODE_ENABLED";
+
/**
- * Key for garage mode maintenance window.
+ * DEPRECATED. Will be removed in Q. Key for garage mode maintenance window.
+ * @deprecated not used by GarageMode anymore. Will be removed in Q.
*/
+ @Deprecated
public static final String KEY_GARAGE_MODE_MAINTENANCE_WINDOW =
"android.car.GARAGE_MODE_MAINTENANCE_WINDOW";
diff --git a/car-lib/src/android/car/settings/GarageModeSettingsObserver.java b/car-lib/src/android/car/settings/GarageModeSettingsObserver.java
deleted file mode 100644
index 8b58ed6..0000000
--- a/car-lib/src/android/car/settings/GarageModeSettingsObserver.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (C) 2016 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.settings;
-
-import android.content.Context;
-import android.database.ContentObserver;
-import android.net.Uri;
-import android.os.Handler;
-import android.provider.Settings;
-
-import java.lang.ref.WeakReference;
-
-/**
- * A content observer for garage mode settings.
- * @hide
- */
-public abstract class GarageModeSettingsObserver extends ContentObserver {
-
- public static final Uri GARAGE_MODE_ENABLED_URI =
- Settings.Global.getUriFor(CarSettings.Global.KEY_GARAGE_MODE_ENABLED);
- public static final Uri GARAGE_MODE_WAKE_UP_TIME_URI =
- Settings.Global.getUriFor(CarSettings.Global.KEY_GARAGE_MODE_WAKE_UP_TIME);
- public static final Uri GARAGE_MODE_MAINTENANCE_WINDOW_URI =
- Settings.Global.getUriFor(CarSettings.Global.KEY_GARAGE_MODE_MAINTENANCE_WINDOW);
-
- public static final Uri[] GARAGE_SETTING_URIS = {GARAGE_MODE_ENABLED_URI,
- GARAGE_MODE_WAKE_UP_TIME_URI, GARAGE_MODE_MAINTENANCE_WINDOW_URI};
-
- private final WeakReference<Context> mContext;
-
- public GarageModeSettingsObserver(Context context, Handler handler) {
- super(handler);
- mContext = new WeakReference<Context>(context);
- }
-
- public void register() {
- if (mContext.get() == null) {
- return;
- }
- for (Uri uri : GARAGE_SETTING_URIS) {
- mContext.get().getContentResolver().registerContentObserver(
- uri, false, this);
- }
- }
-
- public void unregister() {
- if (mContext.get() == null) {
- return;
- }
- mContext.get().getContentResolver().unregisterContentObserver(this);
- }
-
-}
diff --git a/car-lib/src/android/car/user/CarUserManagerHelper.java b/car-lib/src/android/car/user/CarUserManagerHelper.java
index ce50943..94849ee 100644
--- a/car-lib/src/android/car/user/CarUserManagerHelper.java
+++ b/car-lib/src/android/car/user/CarUserManagerHelper.java
@@ -57,6 +57,10 @@
public class CarUserManagerHelper {
private static final String TAG = "CarUserManagerHelper";
private static final String HEADLESS_SYSTEM_USER = "android.car.systemuser.headless";
+
+ // Place holder for user name of the first user created.
+ public static final String DEFAULT_FIRST_ADMIN_NAME = "Driver";
+
/**
* Default set of restrictions for Non-Admin users.
*/
@@ -538,6 +542,13 @@
}
/**
+ * Checks if the foreground user is a demo user.
+ */
+ public boolean isForegroundUserDemo() {
+ return getCurrentForegroundUserInfo().isDemo();
+ }
+
+ /**
* Checks if the foreground user is ephemeral.
*/
public boolean isForegroundUserEphemeral() {
@@ -583,6 +594,23 @@
return !foregroundUserHasUserRestriction(UserManager.DISALLOW_ADD_USER);
}
+ /**
+ * Checks if the current process user can modify accounts. Demo and Guest users cannot modify
+ * accounts even if the DISALLOW_MODIFY_ACCOUNTS restriction is not applied.
+ */
+ public boolean canForegroundUserModifyAccounts() {
+ return !foregroundUserHasUserRestriction(UserManager.DISALLOW_MODIFY_ACCOUNTS)
+ && !isForegroundUserDemo()
+ && !isForegroundUserGuest();
+ }
+
+ /**
+ * Checks if the foreground user can switch to other users.
+ */
+ public boolean canForegroundUserSwitchUsers() {
+ return !foregroundUserHasUserRestriction(UserManager.DISALLOW_USER_SWITCH);
+ }
+
// Current process user information accessors
/**
@@ -774,10 +802,9 @@
return false;
}
- // Not allow to delete the last admin user on the device for now.
+ // Try to create a new admin before deleting the current one.
if (userInfo.isAdmin() && getAllAdminUsers().size() <= 1) {
- Log.w(TAG, "User " + userInfo.id + " is the last admin user on device.");
- return false;
+ return removeLastAdmin(userInfo);
}
if (!isCurrentProcessAdminUser() && !isCurrentProcessUser(userInfo)) {
@@ -787,12 +814,32 @@
}
if (userInfo.id == getCurrentForegroundUserId()) {
+ if (!canCurrentProcessSwitchUsers()) {
+ // If we can't switch to a different user, we can't exit this one and therefore
+ // can't delete it.
+ Log.w(TAG, "User switching is not allowed. Current user cannot be deleted");
+ return false;
+ }
startNewGuestSession(guestUserName);
}
return mUserManager.removeUser(userInfo.id);
}
+ private boolean removeLastAdmin(UserInfo userInfo) {
+ Log.i(TAG, "User " + userInfo.id
+ + " is the last admin user on device. Creating a new admin.");
+
+ UserInfo newAdmin = createNewAdminUser(DEFAULT_FIRST_ADMIN_NAME);
+ if (newAdmin == null) {
+ Log.w(TAG, "Couldn't create another admin, cannot delete current user.");
+ return false;
+ }
+
+ switchToUser(newAdmin);
+ return mUserManager.removeUser(userInfo.id);
+ }
+
/**
* Switches (logs in) to another user given user id.
*
@@ -804,6 +851,12 @@
// System User doesn't associate with real person, can not be switched to.
return false;
}
+ if (!canCurrentProcessSwitchUsers()) {
+ return false;
+ }
+ if (id == getCurrentForegroundUserId()) {
+ return false;
+ }
return mActivityManager.switchUser(id);
}
@@ -814,10 +867,6 @@
* @return {@code true} if user switching succeed.
*/
public boolean switchToUser(UserInfo userInfo) {
- if (userInfo.id == getCurrentForegroundUserId()) {
- return false;
- }
-
return switchToUserId(userInfo.id);
}
diff --git a/car-maps-placeholder/AndroidManifest.xml b/car-maps-placeholder/AndroidManifest.xml
index 38caf38..8c96130 100644
--- a/car-maps-placeholder/AndroidManifest.xml
+++ b/car-maps-placeholder/AndroidManifest.xml
@@ -31,6 +31,8 @@
android:resizeableActivity="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.DEFAULT"/>
+ <category android:name="android.intent.category.APP_MAPS" />
</intent-filter>
</activity>
</application>
diff --git a/car-support-lib/proguard-release.flags b/car-support-lib/proguard-release.flags
index 4f5f917..bb250cf 100644
--- a/car-support-lib/proguard-release.flags
+++ b/car-support-lib/proguard-release.flags
@@ -1823,6 +1823,7 @@
public void finishOp(java.lang.String, int, java.lang.String);
public void finishOp(int, int, java.lang.String);
public void finishOp(int);
+ public static int getNumOps();
public static java.lang.String[] getOpStrs();
public java.util.List getOpsForPackage(int, java.lang.String, int[]);
public java.util.List getPackagesForOps(int[]);
@@ -4451,7 +4452,6 @@
public int describeContents();
public void dump(boolean);
public void ensureData();
- public void ensureDataForAutofill();
public long getAcquisitionEndTime();
public long getAcquisitionStartTime();
public android.content.ComponentName getActivityComponent();
@@ -8097,6 +8097,7 @@
public void writeToProto(android.util.proto.ProtoOutputStream, long);
+ public static float DEFAULT_MAX_LABEL_SIZE_PX;
public static int DUMP_FLAG_ALL;
public static int DUMP_FLAG_APPLICATION;
public static int DUMP_FLAG_DETAILS;
@@ -10767,7 +10768,6 @@
public boolean isMutable();
public boolean isPremultiplied();
public boolean isRecycled();
- public void makeImmutable();
public void prepareToDraw();
public void reconfigure(int, int, android.graphics.Bitmap$Config);
public void recycle();
@@ -10779,6 +10779,7 @@
public void setHasAlpha(boolean);
public void setHasMipMap(boolean);
public void setHeight(int);
+ public void setImmutable();
public void setNinePatchChunk(byte[]);
public void setPixel(int, int, int);
public void setPixels(int[], int, int, int, int, int, int);
@@ -15111,6 +15112,7 @@
public static int DETECT_CUSTOM;
public static int DETECT_DISK_READ;
public static int DETECT_DISK_WRITE;
+ public static int DETECT_EXPLICIT_GC;
public static int DETECT_NETWORK;
public static int DETECT_RESOURCE_MISMATCH;
public static int DETECT_UNBUFFERED_IO;
@@ -17464,7 +17466,7 @@
protected void finalize();
public void finishInputEvent(android.view.InputEvent, boolean);
public void onBatchedInputEventPending();
- public void onInputEvent(android.view.InputEvent, int);
+ public void onInputEvent(android.view.InputEvent);
}
@@ -17950,6 +17952,7 @@
public static int KEYCODE_ZENKAKU_HANKAKU;
public static int KEYCODE_ZOOM_IN;
public static int KEYCODE_ZOOM_OUT;
+ public static int LAST_KEYCODE;
public static int MAX_KEYCODE;
public static int META_ALT_LEFT_ON;
public static int META_ALT_LOCKED;
@@ -18264,6 +18267,7 @@
public float getAxisValue(int, int);
public int getButtonState();
public int getDeviceId();
+ public int getDisplayId();
public long getDownTime();
public int getEdgeFlags();
public long getEventTime();
@@ -18329,6 +18333,7 @@
public boolean isTargetAccessibilityFocus();
public boolean isTouchEvent();
public boolean isWithinBoundsNoHistory(float, float, float, float);
+ public static android.view.MotionEvent obtain(long, long, int, int, android.view.MotionEvent$PointerProperties[], android.view.MotionEvent$PointerCoords[], int, int, float, float, int, int, int, int, int);
public static android.view.MotionEvent obtain(long, long, int, int, android.view.MotionEvent$PointerProperties[], android.view.MotionEvent$PointerCoords[], int, int, float, float, int, int, int, int);
public static android.view.MotionEvent obtain(long, long, int, int, int[], android.view.MotionEvent$PointerCoords[], int, float, float, int, int, int, int);
public static android.view.MotionEvent obtain(long, long, int, float, float, float, float, int, float, float, int, int);
@@ -18342,6 +18347,7 @@
public void setAction(int);
public void setActionButton(int);
public void setButtonState(int);
+ public void setDisplayId(int);
public void setDownTime(long);
public void setEdgeFlags(int);
public void setHoverExitPending(boolean);
@@ -19085,7 +19091,6 @@
public void notifyFramePending();
public static void overrideProperty(java.lang.String, java.lang.String);
public void removeRenderNode(android.view.RenderNode);
- public void serializeDisplayListTree();
public void setContentDrawBounds(int, int, int, int);
public static void setContextPriority(int);
public static void setDebuggingEnabled(boolean);
@@ -23409,6 +23414,8 @@
protected android.widget.Toolbar$LayoutParams generateLayoutParams(android.view.ViewGroup$LayoutParams);
protected android.view.ViewGroup$LayoutParams generateLayoutParams(android.view.ViewGroup$LayoutParams);
public android.view.ViewGroup$LayoutParams generateLayoutParams(android.util.AttributeSet);
+ public java.lang.CharSequence getCollapseContentDescription();
+ public android.graphics.drawable.Drawable getCollapseIcon();
public int getContentInsetEnd();
public int getContentInsetEndWithActions();
public int getContentInsetLeft();
@@ -23449,6 +23456,10 @@
protected android.os.Parcelable onSaveInstanceState();
protected void onSetLayoutParams(android.view.View, android.view.ViewGroup$LayoutParams);
public boolean onTouchEvent(android.view.MotionEvent);
+ public void setCollapseContentDescription(int);
+ public void setCollapseContentDescription(java.lang.CharSequence);
+ public void setCollapseIcon(int);
+ public void setCollapseIcon(android.graphics.drawable.Drawable);
public void setCollapsible(boolean);
public void setContentInsetEndWithActions(int);
public void setContentInsetStartWithNavigation(int);
diff --git a/car-usb-handler/res/layout/usb_host.xml b/car-usb-handler/res/layout/usb_host.xml
index fbcc608..7a13c4f 100644
--- a/car-usb-handler/res/layout/usb_host.xml
+++ b/car-usb-handler/res/layout/usb_host.xml
@@ -28,7 +28,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView
- android:text="@+string/usb_resolving_handlers"
+ android:text="@string/usb_resolving_handlers"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical" />
diff --git a/car_product/build/car.mk b/car_product/build/car.mk
index 0250813..7c08389 100644
--- a/car_product/build/car.mk
+++ b/car_product/build/car.mk
@@ -23,7 +23,6 @@
Bluetooth \
OneTimeInitializer \
Provision \
- SystemUI \
SystemUpdater
PRODUCT_PACKAGES += \
@@ -42,6 +41,7 @@
android.car.cluster.loggingrenderer \
DirectRenderingClusterSample \
com.android.car.powertestservice \
+ GarageModeTestApp \
# SEPolicy for test apps / services
BOARD_SEPOLICY_DIRS += packages/services/Car/car_product/sepolicy/test
@@ -91,10 +91,12 @@
CarRadioApp \
OverviewApp \
CarLauncher \
+ CarSystemUI \
CarLensPickerApp \
LocalMediaPlayer \
CarMediaApp \
CarMessengerApp \
+ CarNotification \
CarHvacApp \
CarMapsPlaceholder \
CarLatinIME \
diff --git a/car_product/build/car_base.mk b/car_product/build/car_base.mk
index 6788a49..244e2e8 100644
--- a/car_product/build/car_base.mk
+++ b/car_product/build/car_base.mk
@@ -53,6 +53,7 @@
libwebrtc_audio_preprocessing \
wifi-service \
A2dpSinkService \
+ PackageInstaller
# EVS resources
PRODUCT_PACKAGES += android.automotive.evs.manager@1.0
diff --git a/car_product/overlay/frameworks/base/core/res/res/color/car_borderless_button_text_color.xml b/car_product/overlay/frameworks/base/core/res/res/color/car_borderless_button_text_color.xml
new file mode 100644
index 0000000..01fc20b
--- /dev/null
+++ b/car_product/overlay/frameworks/base/core/res/res/color/car_borderless_button_text_color.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 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.
+-->
+<!-- Default text colors for car buttons when enabled/disabled. -->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:color="@color/car_grey_700" android:state_enabled="false"/>
+ <item android:color="?android:attr/colorButtonNormal"/>
+</selector>
diff --git a/car_product/overlay/frameworks/base/core/res/res/color/car_button_text_color.xml b/car_product/overlay/frameworks/base/core/res/res/color/car_button_text_color.xml
new file mode 100644
index 0000000..7add316
--- /dev/null
+++ b/car_product/overlay/frameworks/base/core/res/res/color/car_button_text_color.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 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.
+-->
+<!-- Default text colors for car buttons when enabled/disabled. -->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:color="@color/car_grey_700" android:state_enabled="false"/>
+ <item android:color="@color/car_action1"/>
+</selector>
diff --git a/car_product/overlay/frameworks/base/core/res/res/drawable/car_button_background.xml b/car_product/overlay/frameworks/base/core/res/res/drawable/car_button_background.xml
new file mode 100644
index 0000000..ccc4e22
--- /dev/null
+++ b/car_product/overlay/frameworks/base/core/res/res/drawable/car_button_background.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 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.
+-->
+<!-- Default background styles for car buttons when enabled/disabled. -->
+<ripple
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:color="?attr/colorControlHighlight">
+ <item>
+ <selector>
+ <item android:state_enabled="false">
+ <shape android:shape="rectangle">
+ <corners android:radius="@dimen/car_button_radius"/>
+ <solid android:color="@color/car_grey_300"/>
+ </shape>
+ </item>
+ <item>
+ <shape android:shape="rectangle">
+ <corners android:radius="@dimen/car_button_radius"/>
+ <solid android:color="?android:attr/colorButtonNormal"/>
+ </shape>
+ </item>
+ </selector>
+ </item>
+</ripple>
diff --git a/car_product/overlay/frameworks/base/core/res/res/drawable/car_seekbar_thumb.xml b/car_product/overlay/frameworks/base/core/res/res/drawable/car_seekbar_thumb.xml
new file mode 100644
index 0000000..3729a3b
--- /dev/null
+++ b/car_product/overlay/frameworks/base/core/res/res/drawable/car_seekbar_thumb.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 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.
+-->
+
+<shape
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="oval">
+ <solid android:color="@color/car_accent" />
+ <size
+ android:width="@dimen/car_seekbar_thumb_size"
+ android:height="@dimen/car_seekbar_thumb_size" />
+</shape>
diff --git a/car_product/overlay/frameworks/base/core/res/res/drawable/car_seekbar_thumb_dark.xml b/car_product/overlay/frameworks/base/core/res/res/drawable/car_seekbar_thumb_dark.xml
new file mode 100644
index 0000000..a469ada
--- /dev/null
+++ b/car_product/overlay/frameworks/base/core/res/res/drawable/car_seekbar_thumb_dark.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 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.
+-->
+
+<shape
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="oval">
+ <solid android:color="@color/car_accent_dark" />
+ <size
+ android:width="@dimen/car_seekbar_thumb_size"
+ android:height="@dimen/car_seekbar_thumb_size" />
+</shape>
diff --git a/car_product/overlay/frameworks/base/core/res/res/drawable/car_seekbar_thumb_light.xml b/car_product/overlay/frameworks/base/core/res/res/drawable/car_seekbar_thumb_light.xml
new file mode 100644
index 0000000..0509858
--- /dev/null
+++ b/car_product/overlay/frameworks/base/core/res/res/drawable/car_seekbar_thumb_light.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 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.
+-->
+
+<shape
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="oval">
+ <solid android:color="@color/car_accent_light" />
+ <size
+ android:width="@dimen/car_seekbar_thumb_size"
+ android:height="@dimen/car_seekbar_thumb_size" />
+</shape>
diff --git a/car_product/overlay/frameworks/base/core/res/res/drawable/car_seekbar_track.xml b/car_product/overlay/frameworks/base/core/res/res/drawable/car_seekbar_track.xml
new file mode 100644
index 0000000..fd112b0
--- /dev/null
+++ b/car_product/overlay/frameworks/base/core/res/res/drawable/car_seekbar_track.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 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.
+-->
+
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:id="@android:id/background">
+ <shape android:shape="line">
+ <stroke
+ android:width="@dimen/car_seekbar_height"
+ android:color="@color/car_seekbar_track_background" />
+ </shape>
+ </item>
+ <item android:id="@android:id/secondaryProgress">
+ <clip>
+ <shape android:shape="line">
+ <stroke
+ android:width="@dimen/car_seekbar_height"
+ android:color="@color/car_seekbar_track_secondary_progress" />
+ </shape>
+ </clip>
+ </item>
+ <item android:id="@android:id/progress">
+ <clip>
+ <shape android:shape="line">
+ <stroke
+ android:width="@dimen/car_seekbar_height"
+ android:color="@color/car_accent" />
+ </shape>
+ </clip>
+ </item>
+</layer-list>
diff --git a/car_product/overlay/frameworks/base/core/res/res/drawable/car_seekbar_track_dark.xml b/car_product/overlay/frameworks/base/core/res/res/drawable/car_seekbar_track_dark.xml
new file mode 100644
index 0000000..b7fa379
--- /dev/null
+++ b/car_product/overlay/frameworks/base/core/res/res/drawable/car_seekbar_track_dark.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 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.
+-->
+
+<!-- Drawable of seekbar track. Uses dark color for track. -->
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:id="@android:id/background">
+ <shape android:shape="line">
+ <stroke
+ android:width="@dimen/car_seekbar_height"
+ android:color="@color/car_seekbar_track_background_dark" />
+ </shape>
+ </item>
+ <item android:id="@android:id/secondaryProgress">
+ <clip>
+ <shape android:shape="line">
+ <stroke
+ android:width="@dimen/car_seekbar_height"
+ android:color="@color/car_seekbar_track_secondary_progress" />
+ </shape>
+ </clip>
+ </item>
+ <item android:id="@android:id/progress">
+ <clip>
+ <shape android:shape="line">
+ <stroke
+ android:width="@dimen/car_seekbar_height"
+ android:color="@color/car_accent_light" />
+ </shape>
+ </clip>
+ </item>
+</layer-list>
diff --git a/car_product/overlay/frameworks/base/core/res/res/drawable/car_seekbar_track_light.xml b/car_product/overlay/frameworks/base/core/res/res/drawable/car_seekbar_track_light.xml
new file mode 100644
index 0000000..a9df2b6
--- /dev/null
+++ b/car_product/overlay/frameworks/base/core/res/res/drawable/car_seekbar_track_light.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 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.
+-->
+
+<!-- Drawable of seekbar track. Uses light color for track. -->
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:id="@android:id/background">
+ <shape android:shape="line">
+ <stroke
+ android:width="@dimen/car_seekbar_height"
+ android:color="@color/car_seekbar_track_background_light" />
+ </shape>
+ </item>
+ <item android:id="@android:id/secondaryProgress">
+ <clip>
+ <shape android:shape="line">
+ <stroke
+ android:width="@dimen/car_seekbar_height"
+ android:color="@color/car_seekbar_track_secondary_progress" />
+ </shape>
+ </clip>
+ </item>
+ <item android:id="@android:id/progress">
+ <clip>
+ <shape android:shape="line">
+ <stroke
+ android:width="@dimen/car_seekbar_height"
+ android:color="@color/car_accent_dark" />
+ </shape>
+ </clip>
+ </item>
+</layer-list>
diff --git a/car_product/overlay/frameworks/base/core/res/res/layout/alert_dialog_button_bar_material.xml b/car_product/overlay/frameworks/base/core/res/res/layout/alert_dialog_button_bar_material.xml
index 7203849..f929d10 100644
--- a/car_product/overlay/frameworks/base/core/res/res/layout/alert_dialog_button_bar_material.xml
+++ b/car_product/overlay/frameworks/base/core/res/res/layout/alert_dialog_button_bar_material.xml
@@ -26,9 +26,9 @@
<com.android.internal.widget.ButtonBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_marginStart="@dimen/car_keyline_1"
- android:layout_marginEnd="@dimen/car_keyline_1"
- android:layout_marginTop="@dimen/car_padding_2"
+ android:paddingStart="@dimen/car_keyline_1"
+ android:paddingEnd="@dimen/car_keyline_1"
+ android:paddingTop="@dimen/car_padding_2"
android:layoutDirection="locale"
android:orientation="horizontal"
android:gravity="center_vertical">
diff --git a/car_product/overlay/frameworks/base/core/res/res/values-night/themes.xml b/car_product/overlay/frameworks/base/core/res/res/values-night/themes.xml
new file mode 100644
index 0000000..6f89ffd
--- /dev/null
+++ b/car_product/overlay/frameworks/base/core/res/res/values-night/themes.xml
@@ -0,0 +1,18 @@
+<!-- Copyright (C) 2018 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>
+ <style name="Theme.DeviceDefaultBase.DayNight">
+ </style>
+</resources>
diff --git a/car_product/overlay/frameworks/base/core/res/res/values-sw900dp/dimens.xml b/car_product/overlay/frameworks/base/core/res/res/values-sw900dp/dimens.xml
deleted file mode 100644
index d1af884..0000000
--- a/car_product/overlay/frameworks/base/core/res/res/values-sw900dp/dimens.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- * 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.
-*/
--->
-<resources>
-
- <!-- Height of the bottom navigation / system bar. -->
- <dimen name="navigation_bar_height">112dp</dimen>
-
- <!-- Height of the bottom navigation bar in landscape; often
- the same as @dimen/navigation_bar_height -->
- <dimen name="navigation_bar_height_landscape">112dp</dimen>
-
-</resources>
diff --git a/car_product/overlay/frameworks/base/core/res/res/values-w1920dp/dimens.xml b/car_product/overlay/frameworks/base/core/res/res/values-w1920dp/dimens.xml
index dcb92dc..389f162 100644
--- a/car_product/overlay/frameworks/base/core/res/res/values-w1920dp/dimens.xml
+++ b/car_product/overlay/frameworks/base/core/res/res/values-w1920dp/dimens.xml
@@ -15,6 +15,5 @@
-->
<resources>
- <dimen name="status_bar_height">56dp</dimen>
<dimen name="car_keyline_4">184dp</dimen>
</resources>
diff --git a/car_product/overlay/frameworks/base/core/res/res/values/colors.xml b/car_product/overlay/frameworks/base/core/res/res/values/colors.xml
index 37dc0bf..7057083 100644
--- a/car_product/overlay/frameworks/base/core/res/res/values/colors.xml
+++ b/car_product/overlay/frameworks/base/core/res/res/values/colors.xml
@@ -180,8 +180,21 @@
car_scrollbar_thumb. -->
<color name="car_scrollbar_thumb_inverse">@color/car_scrollbar_thumb_light</color>
+ <!-- The color of the seekbar track secondary progress in SeekbarListItem. -->
+ <color name="car_seekbar_track_secondary_progress">@color/car_grey_500</color>
+
+ <!-- The lighter and darker color for the seekbar track background. -->
+ <color name="car_seekbar_track_background_light">@color/car_grey_400</color>
+ <color name="car_seekbar_track_background_dark">@color/car_grey_700</color>
+ <!-- The color of the seekbar track background in SeekbarListItem. This color is assumed to be
+ on a light-colored background. -->
+ <color name="car_seekbar_track_background">@color/car_seekbar_track_background_light</color>
+
<!-- Misc colors -->
<color name="car_highlight_light">@color/car_teal_700</color>
<color name="car_highlight_dark">@color/car_teal_200</color>
<color name="car_highlight">@color/car_highlight_light</color>
+ <color name="car_accent_light">@color/car_highlight_light</color>
+ <color name="car_accent_dark">@color/car_highlight_dark</color>
+ <color name="car_accent">@color/car_highlight</color>
</resources>
diff --git a/car_product/overlay/frameworks/base/core/res/res/values/dimens.xml b/car_product/overlay/frameworks/base/core/res/res/values/dimens.xml
index 2adc535..31218dd 100644
--- a/car_product/overlay/frameworks/base/core/res/res/values/dimens.xml
+++ b/car_product/overlay/frameworks/base/core/res/res/values/dimens.xml
@@ -17,12 +17,13 @@
*/
-->
<resources>
- <dimen name="status_bar_height">36dp</dimen>
-
- <!-- Both of these are used in separate positions so make sure that they remain the same. -->
- <dimen name="navigation_bar_height_car_mode">112dp</dimen>
- <dimen name="navigation_bar_height_landscape">112dp</dimen>
- <dimen name="status_bar_icon_size">40dp</dimen>
+ <dimen name="status_bar_height">96dp</dimen>
+ <dimen name="status_bar_height_landscape">96dp</dimen>
+ <dimen name="status_bar_height_portrait">96dp</dimen>
+ <dimen name="car_qs_header_system_icons_area_height">96dp</dimen>
+ <dimen name="navigation_bar_height">128dp</dimen>
+ <dimen name="navigation_bar_height_landscape">128dp</dimen>
+ <dimen name="status_bar_icon_size">36dp</dimen>
<!-- The height of the header of a notification. -->
<dimen name="notification_header_height">58dp</dimen>
@@ -109,10 +110,21 @@
<dimen name="notification_progress_margin_top">16dp</dimen>
<!-- Text size for car -->
- <dimen name="car_title2_size">40sp</dimen>
- <dimen name="car_body1_size">40sp</dimen>
- <dimen name="car_body2_size">32sp</dimen>
- <dimen name="car_action1_size">32sp</dimen>
+ <dimen name="car_title_size">32sp</dimen>
+ <dimen name="car_title2_size">32sp</dimen>
+ <dimen name="car_headline1_size">45sp</dimen>
+ <dimen name="car_headline2_size">32sp</dimen>
+ <dimen name="car_headline3_size">24sp</dimen>
+ <dimen name="car_headline4_size">20sp</dimen>
+ <dimen name="car_body1_size">32sp</dimen>
+ <dimen name="car_body2_size">26sp</dimen>
+ <dimen name="car_body3_size">16sp</dimen>
+ <dimen name="car_body4_size">14sp</dimen>
+ <dimen name="car_body5_size">18sp</dimen>
+ <dimen name="car_label1_size">26sp</dimen>
+ <dimen name="car_label2_size">64sp</dimen>
+ <dimen name="car_action1_size">26sp</dimen>
+ <dimen name="car_action2_size">26sp</dimen>
<!-- Common icon size for car app -->
<dimen name="car_icon_size">56dp</dimen>
@@ -139,6 +151,26 @@
<dimen name="car_keyline_3">152dp</dimen>
<dimen name="car_keyline_4">182dp</dimen>
+ <!-- Buttons -->
+ <dimen name="car_button_height">56dp</dimen>
+ <dimen name="car_button_min_width">158dp</dimen>
+ <dimen name="car_button_horizontal_padding">@dimen/car_padding_4</dimen>
+ <dimen name="car_borderless_button_horizontal_padding">0dp</dimen>
+ <dimen name="car_button_radius">@dimen/car_radius_1</dimen>
+ <dimen name="car_pill_button_size">56dp</dimen>
+
+ <!-- Seekbar -->
+ <dimen name="car_seekbar_height">6dp</dimen>
+ <dimen name="car_seekbar_padding">26dp</dimen>
+ <dimen name="car_seekbar_thumb_size">24dp</dimen>
+ <dimen name="car_seekbar_thumb_stroke">1dp</dimen>
+ <!-- The space between seekbar and text in ListItem. This value is based on car_seekbar_padding.
+ It brings seekbar and text closer for visual balance while maintaining touch area. -->
+ <dimen name="car_seekbar_text_overlap">-20dp</dimen>
+
+ <!-- Progress Bar -->
+ <dimen name="car_progress_bar_height">@dimen/car_seekbar_height</dimen>
+
<!-- Make the dots in lock pattern thicker in Car -->
<dimen name="lock_pattern_dot_size">20dp</dimen>
</resources>
diff --git a/car_product/overlay/frameworks/base/core/res/res/values/styles.xml b/car_product/overlay/frameworks/base/core/res/res/values/styles.xml
index f654f3d..5c2968e 100644
--- a/car_product/overlay/frameworks/base/core/res/res/values/styles.xml
+++ b/car_product/overlay/frameworks/base/core/res/res/values/styles.xml
@@ -77,6 +77,20 @@
</style>
<!-- Car text -->
+ <style name="CarBody1">
+ <item name="android:textStyle">normal</item>
+ <item name="android:textSize">@dimen/car_body1_size</item>
+ <item name="android:textColor">@color/car_body1</item>
+ </style>
+
+ <style name="CarBody1.Light">
+ <item name="android:textColor">@color/car_body1_light</item>
+ </style>
+
+ <style name="CarBody1.Dark">
+ <item name="android:textColor">@color/car_body2_dark</item>
+ </style>
+
<style name="CarBody2">
<item name="android:textStyle">normal</item>
<item name="android:textSize">@dimen/car_body2_size</item>
@@ -89,6 +103,20 @@
<style name="CarBody2.Light">
<item name="android:textColor">@color/car_body2_light</item>
</style>
+
+ <style name="CarBody3">
+ <item name="android:textStyle">normal</item>
+ <item name="android:textSize">@dimen/car_body3_size</item>
+ <item name="android:textColor">@color/car_body3</item>
+ </style>
+
+ <!-- The smallest styling for body text. The color of this text changes based on the day/night
+ mode. -->
+ <style name="CarBody4">
+ <item name="android:textStyle">normal</item>
+ <item name="android:textSize">@dimen/car_body4_size</item>
+ <item name="android:textColor">@color/car_body4</item>
+ </style>
<style name="CarAction1">
<item name="android:textStyle">bold</item>
@@ -119,4 +147,55 @@
<style name="CarTitle.Light" >
<item name="android:textColor">@color/car_title_light</item>
</style>
+
+ <!-- ======= -->
+ <!-- Widgets -->
+ <!-- ======= -->
+
+ <!-- The styles for the regular and borderless buttons. -->
+ <style name="Widget.CarDefault.Button" parent="Widget.DeviceDefault.Button">
+ <item name="android:fontFamily">sans-serif-medium</item>
+ <item name="android:layout_height">@dimen/car_button_height</item>
+ <item name="android:minWidth">@dimen/car_button_min_width</item>
+ <item name="android:paddingStart">@dimen/car_button_horizontal_padding</item>
+ <item name="android:paddingEnd">@dimen/car_button_horizontal_padding</item>
+ <item name="android:textSize">@dimen/car_action1_size</item>
+ <item name="android:background">@drawable/car_button_background</item>
+ <item name="android:textColor">@color/car_button_text_color</item>
+ </style>
+
+ <style name="Widget.CarDefault.Button.Borderless.Colored" parent="Widget.DeviceDefault.Button.Borderless.Colored">
+ <item name="android:fontFamily">sans-serif-medium</item>
+ <item name="android:layout_height">@dimen/car_button_height</item>
+ <item name="android:minWidth">@dimen/car_button_min_width</item>
+ <item name="android:paddingStart">@dimen/car_borderless_button_horizontal_padding</item>
+ <item name="android:paddingEnd">@dimen/car_borderless_button_horizontal_padding</item>
+ <item name="android:textSize">@dimen/car_action1_size</item>
+ <item name="android:textColor">@color/car_borderless_button_text_color</item>
+ </style>
+
+ <style name="Widget.CarDefault.Button.Borderless.Colored.Light">
+ <item name="android:textColor">@color/car_borderless_button_text_color</item>
+ </style>
+
+ <style name="Widget.CarDefault.Button.Borderless.Colored.Dark">
+ <item name="android:textColor">@color/car_borderless_button_text_color</item>
+ </style>
+
+ <!-- Style for the progress bars. -->
+ <style name="Widget.CarDefault.ProgressBar.Horizontal" parent="Widget.DeviceDefault.ProgressBar.Horizontal">
+ <item name="android:minHeight">@dimen/car_progress_bar_height</item>
+ <item name="android:maxHeight">@dimen/car_progress_bar_height</item>
+ </style>
+
+ <style name="Widget.CarDefault.EditText" parent="Widget.DeviceDefault.EditText">
+ <item name="android:textColor">?attr/editTextColor</item>
+ <item name="android:textAppearance">@style/CarBody1</item>
+ </style>
+
+ <!-- Styling for the seek bars. -->
+ <style name="Widget.CarDefault.SeekBar" parent="Widget.DeviceDefault.SeekBar">
+ <item name="android:progressDrawable">@drawable/car_seekbar_track</item>
+ <item name="android:thumb">@drawable/car_seekbar_thumb</item>
+ </style>
</resources>
diff --git a/car_product/overlay/frameworks/base/core/res/res/values/themes.xml b/car_product/overlay/frameworks/base/core/res/res/values/themes.xml
new file mode 100644
index 0000000..75fb3d1
--- /dev/null
+++ b/car_product/overlay/frameworks/base/core/res/res/values/themes.xml
@@ -0,0 +1,31 @@
+<!-- Copyright (C) 2018 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>
+ <style name="Theme.DeviceDefaultBase.DayNight" />
+ <style name="Theme.DeviceDefault" parent="Theme.DeviceDefaultBase.DayNight">
+ <item name="android:colorAccent">@color/car_highlight</item>
+ <item name="android:colorButtonNormal">@color/car_highlight</item>
+ <item name="android:colorControlHighlight">@color/car_card_ripple_background</item>
+ <item name="android:buttonStyle">@style/Widget.CarDefault.Button</item>
+ <item name="android:borderlessButtonStyle">@style/Widget.CarDefault.Button.Borderless.Colored</item>
+ <item name="android:progressBarStyleHorizontal">@style/Widget.CarDefault.ProgressBar.Horizontal</item>
+ <item name="android:textColorHint">@color/car_body2</item>
+ <item name="android:editTextStyle">@style/Widget.CarDefault.EditText</item>
+ <item name="android:editTextColor">@color/car_body1</item>
+ <item name="android:colorControlNormal">@color/car_body2</item>
+ <item name="android:seekBarStyle">@style/Widget.CarDefault.SeekBar</item>
+ <item name="android:colorControlHighlight">@color/car_card_ripple_background_inverse</item>
+ </style>
+</resources>
diff --git a/car_product/overlay/frameworks/base/packages/SystemUI/res/drawable/car_ic_apps.xml b/car_product/overlay/frameworks/base/packages/SystemUI/res/drawable/car_ic_apps.xml
deleted file mode 100644
index f5fbe6d..0000000
--- a/car_product/overlay/frameworks/base/packages/SystemUI/res/drawable/car_ic_apps.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<!--
- Copyright (C) 2018 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.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="56dp"
- android:height="56dp"
- android:viewportWidth="48"
- android:viewportHeight="48">
-
- <path
- android:fillColor="#FFFFFF"
- android:pathData="M8 16h8V8H8v8zm12 24h8v-8h-8v8zM8 40h8v-8H8v8zm0-12h8v-8H8v8zm12 0h8v-8h-8v8zM32
-8v8h8V8h-8zm-12 8h8V8h-8v8zm12 12h8v-8h-8v8zm0 12h8v-8h-8v8z" />
- <path
- android:pathData="M0 0h48v48H0z" />
-</vector>
\ No newline at end of file
diff --git a/car_product/overlay/frameworks/base/packages/SystemUI/res/drawable/car_ic_car.xml b/car_product/overlay/frameworks/base/packages/SystemUI/res/drawable/car_ic_car.xml
deleted file mode 100644
index ba52f1f..0000000
--- a/car_product/overlay/frameworks/base/packages/SystemUI/res/drawable/car_ic_car.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<!--
- Copyright (C) 2016 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.
--->
-<vector android:height="56dp" android:viewportHeight="24.0"
- android:viewportWidth="24.0" android:width="56dp" xmlns:android="http://schemas.android.com/apk/res/android">
- <path android:fillColor="#FFFFFFFF"
- android:pathData="M7.289,7.507C7.166,7.242 7.282,7.126 7.546,7.249L12.688,10.138C13.325,10.442 13.77,11.087 13.77,11.841C13.77,12.884 12.923,13.73 11.88,13.73C11.126,13.73 10.481,13.286 10.178,12.648L7.289,7.507Z"
- android:strokeColor="#00000000" android:strokeWidth="1"/>
- <path android:fillColor="#FFFFFFFF"
- android:pathData="M19.068,4.928C15.534,1.392 10.027,1.061 6.114,3.922L7.544,5.353C10.655,3.263 14.905,3.525 17.653,6.276C20.778,9.402 20.779,14.862 17.653,17.531L6.337,17.531C3.562,14.862 3.256,10.517 5.411,7.397L3.982,6.001C1.06,9.922 1.366,15.506 4.922,19.065C8.829,22.974 15.163,22.981 19.071,19.069C22.98,15.159 22.974,8.837 19.068,4.928L19.068,4.928Z"
- android:strokeColor="#00000000" android:strokeWidth="1"/>
-</vector>
diff --git a/car_product/overlay/frameworks/base/packages/SystemUI/res/drawable/car_ic_hvac.xml b/car_product/overlay/frameworks/base/packages/SystemUI/res/drawable/car_ic_hvac.xml
deleted file mode 100644
index bdc44b3..0000000
--- a/car_product/overlay/frameworks/base/packages/SystemUI/res/drawable/car_ic_hvac.xml
+++ /dev/null
@@ -1,51 +0,0 @@
-<!--
- Copyright (C) 2018 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.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="37dp"
- android:height="31dp"
- android:viewportWidth="37"
- android:viewportHeight="31">
-
- <group
- android:translateX="-4.000000"
- android:translateY="-6.000000">
- <group
- android:translateX="5.000000"
- android:translateY="5.000000">
- <path
- android:fillType="evenOdd"
- android:strokeColor="#FAFAFA"
- android:strokeWidth="3.5"
- android:pathData="M0.320769938,6.07518051 C6.46754647,1.46509811 12.4222362,1.46509811
-18.1848392,6.07518051 C23.9474422,10.6852629 29.3258717,10.4931761
-34.3201276,5.49892021" />
- <path
- android:fillType="evenOdd"
- android:strokeColor="#FAFAFA"
- android:strokeWidth="3.5"
- android:pathData="M0.320769938,17.0751805 C6.46754647,12.4650981 12.4222362,12.4650981
-18.1848392,17.0751805 C23.9474422,21.6852629 29.3258717,21.4931761
-34.3201276,16.4989202" />
- <path
- android:fillType="evenOdd"
- android:strokeColor="#FAFAFA"
- android:strokeWidth="3.5"
- android:pathData="M0.320769938,28.0751805 C6.46754647,23.4650981 12.4222362,23.4650981
-18.1848392,28.0751805 C23.9474422,32.6852629 29.3258717,32.4931761
-34.3201276,27.4989202" />
- </group>
- </group>
-</vector>
\ No newline at end of file
diff --git a/car_product/overlay/frameworks/base/packages/SystemUI/res/drawable/car_ic_music.xml b/car_product/overlay/frameworks/base/packages/SystemUI/res/drawable/car_ic_music.xml
deleted file mode 100644
index 5ad7537..0000000
--- a/car_product/overlay/frameworks/base/packages/SystemUI/res/drawable/car_ic_music.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<!--
- Copyright (C) 2016 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.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="56dp"
- android:height="56dp"
- android:viewportWidth="48"
- android:viewportHeight="48">
-
- <path
- android:fillAlpha=".1"
- android:strokeAlpha=".1"
- android:pathData="M0 0h48v48H0z" />
- <path
- android:fillColor="#FFFFFFFF"
- android:pathData="M24 2C14.06 2 6 10.06 6 20v14c0 3.31 2.69 6 6 6h6V24h-8v-4c0-7.73 6.27-14
-14-14s14 6.27 14 14v4h-8v16h6c3.31 0 6-2.69 6-6V20c0-9.94-8.06-18-18-18z" />
-</vector>
diff --git a/car_product/overlay/frameworks/base/packages/SystemUI/res/drawable/car_ic_navigation.xml b/car_product/overlay/frameworks/base/packages/SystemUI/res/drawable/car_ic_navigation.xml
deleted file mode 100644
index 980c4d8..0000000
--- a/car_product/overlay/frameworks/base/packages/SystemUI/res/drawable/car_ic_navigation.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<!--
- Copyright (C) 2016 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.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="56dp"
- android:height="56dp"
- android:viewportWidth="48"
- android:viewportHeight="48">
- <path
- android:fillColor="#FFFFFFFF"
- android:pathData="M43.41 22.59l-18-18c-.78-.78-2.05-.78-2.82 0l-18 18c-.78 .78 -.78 2.05 0 2.83l18
-17.99v.01c.78 .78 2.05 .78 2.83 0l18-18c.78-.79 .78 -2.05-.01-2.83zM28
-29v-5h-8v6h-4v-8c0-1.11 .89 -2 2-2h10v-5l7 7-7 7z" />
- <path
- android:pathData="M0 0h48v48H0z" />
-</vector>
diff --git a/car_product/overlay/frameworks/base/packages/SystemUI/res/drawable/car_ic_notification.xml b/car_product/overlay/frameworks/base/packages/SystemUI/res/drawable/car_ic_notification.xml
deleted file mode 100644
index 61d937b..0000000
--- a/car_product/overlay/frameworks/base/packages/SystemUI/res/drawable/car_ic_notification.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<!--
- Copyright (C) 2018 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.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="56dp"
- android:height="56dp"
- android:viewportWidth="48"
- android:viewportHeight="48">
-
- <path
- android:fillColor="#FFFFFF"
- android:pathData="M24 44c2.21 0 4-1.79 4-4h-8c0 2.21 1.79 4 4
-4zm12-12V22c0-6.15-3.27-11.28-9-12.64V8c0-1.66-1.34-3-3-3s-3 1.34-3 3v1.36c-5.73
-1.36-9 6.49-9 12.64v10l-4 4v2h32v-2l-4-4zm-4 2H16V22c0-4.97 3.03-9 8-9s8 4.03 8
-9v12z" />
-</vector>
\ No newline at end of file
diff --git a/car_product/overlay/frameworks/base/packages/SystemUI/res/drawable/car_ic_overview.xml b/car_product/overlay/frameworks/base/packages/SystemUI/res/drawable/car_ic_overview.xml
deleted file mode 100644
index 4651dcb..0000000
--- a/car_product/overlay/frameworks/base/packages/SystemUI/res/drawable/car_ic_overview.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<!--
- Copyright (C) 2016 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.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="56dp"
- android:height="56dp"
- android:viewportWidth="48"
- android:viewportHeight="48">
-
- <path
- android:pathData="M0 0h48v48H0z" />
- <path
- android:fillColor="#FFFFFFFF"
- android:pathData="M24 4C12.95 4 4 12.95 4 24s8.95 20 20 20 20-8.95 20-20S35.05 4 24 4zm0 36c-8.82
-0-16-7.18-16-16S15.18 8 24 8s16 7.18 16 16-7.18 16-16 16z" />
-</vector>
diff --git a/car_product/overlay/frameworks/base/packages/SystemUI/res/drawable/car_ic_phone.xml b/car_product/overlay/frameworks/base/packages/SystemUI/res/drawable/car_ic_phone.xml
deleted file mode 100644
index 87bfdf7..0000000
--- a/car_product/overlay/frameworks/base/packages/SystemUI/res/drawable/car_ic_phone.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<!--
- Copyright (C) 2016 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.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="56dp"
- android:height="56dp"
- android:viewportWidth="48"
- android:viewportHeight="48">
-
- <path
- android:pathData="M0 0h48v48H0z" />
- <path
- android:fillColor="#FFFFFFFF"
- android:pathData="M13.25 21.59c2.88 5.66 7.51 10.29 13.18 13.17l4.4-4.41c.55-.55 1.34-.71
-2.03-.49C35.1 30.6 37.51 31 40 31c1.11 0 2 .89 2 2v7c0 1.11-.89 2-2 2C21.22 42 6
-26.78 6 8c0-1.11 .9 -2 2-2h7c1.11 0 2 .89 2 2 0 2.49 .4 4.9 1.14 7.14 .22 .69
-.06 1.48-.49 2.03l-4.4 4.42z" />
-</vector>
diff --git a/car_product/overlay/frameworks/base/packages/SystemUI/res/drawable/car_ic_seekbar_thumb.xml b/car_product/overlay/frameworks/base/packages/SystemUI/res/drawable/car_ic_seekbar_thumb.xml
deleted file mode 100644
index a29ddc8..0000000
--- a/car_product/overlay/frameworks/base/packages/SystemUI/res/drawable/car_ic_seekbar_thumb.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ 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
- -->
-
-<shape
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="oval">
- <solid android:color="@color/car_teal_700" />
- <size
- android:width="30dp"
- android:height="30dp" />
- <stroke
- android:width="1dp"
- android:color="@color/car_teal_700" />
-</shape>
diff --git a/car_product/overlay/frameworks/base/packages/SystemUI/res/drawable/car_ic_seekbar_track.xml b/car_product/overlay/frameworks/base/packages/SystemUI/res/drawable/car_ic_seekbar_track.xml
deleted file mode 100644
index 2b42d9d..0000000
--- a/car_product/overlay/frameworks/base/packages/SystemUI/res/drawable/car_ic_seekbar_track.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ 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
- -->
-
-<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
- <!-- Use android provided id, as seekbar is expecting that -->
- <item android:id="@android:id/background">
- <shape android:shape="line">
- <corners
- android:radius="3dp"/>
- <stroke
- android:width="3dp"
- android:color="@color/car_grey_300" />
- </shape>
- </item>
- <item android:id="@android:id/progress">
- <clip>
- <shape android:shape="line">
- <stroke
- android:width="6dp"
- android:color="@color/car_teal_700" />
- </shape>
- </clip>
- </item>
-</layer-list>
diff --git a/car_product/overlay/frameworks/base/packages/SystemUI/res/drawable/notification_material_bg.xml b/car_product/overlay/frameworks/base/packages/SystemUI/res/drawable/notification_material_bg.xml
deleted file mode 100644
index 039833b..0000000
--- a/car_product/overlay/frameworks/base/packages/SystemUI/res/drawable/notification_material_bg.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2016 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.
--->
-<ripple xmlns:android="http://schemas.android.com/apk/res/android"
- android:color="@color/notification_ripple_untinted_color">
- <item>
- <shape xmlns:android="http://schemas.android.com/apk/res/android">
- <solid android:color="@color/notification_material_background_color" />
- <corners
- android:radius="@dimen/notification_shadow_radius"/>
- </shape>
- </item>
-</ripple>
diff --git a/car_product/overlay/frameworks/base/packages/SystemUI/res/drawable/notification_material_bg_dim.xml b/car_product/overlay/frameworks/base/packages/SystemUI/res/drawable/notification_material_bg_dim.xml
deleted file mode 100644
index 90c793f..0000000
--- a/car_product/overlay/frameworks/base/packages/SystemUI/res/drawable/notification_material_bg_dim.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2016 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.
--->
-<ripple xmlns:android="http://schemas.android.com/apk/res/android"
- android:color="@color/notification_ripple_untinted_color">
- <item>
- <shape xmlns:android="http://schemas.android.com/apk/res/android">
- <solid android:color="@color/notification_material_background_color" />
- <corners
- android:radius="@dimen/notification_shadow_radius"/>
- </shape>
- </item>
-</ripple>
diff --git a/car_product/overlay/frameworks/base/packages/SystemUI/res/layout/car_navigation_bar.xml b/car_product/overlay/frameworks/base/packages/SystemUI/res/layout/car_navigation_bar.xml
deleted file mode 100644
index a4902cd..0000000
--- a/car_product/overlay/frameworks/base/packages/SystemUI/res/layout/car_navigation_bar.xml
+++ /dev/null
@@ -1,165 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-**
-** Copyright 2018, 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.
-*/
--->
-
-<com.android.systemui.statusbar.car.CarNavigationBarView
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:systemui="http://schemas.android.com/apk/res-auto"
- android:layout_height="match_parent"
- android:layout_width="match_parent"
- android:background="@drawable/system_bar_background">
-
- <LinearLayout
- android:layout_height="match_parent"
- android:layout_width="wrap_content"
- android:paddingStart="@dimen/car_keyline_1"
- android:paddingEnd="@dimen/car_keyline_1"
- android:orientation="horizontal"
- android:id="@+id/nav_buttons"
- android:gravity="center"
- android:layout_weight="1"
- android:animateLayoutChanges="true">
-
- <com.android.systemui.statusbar.car.CarNavigationButton
- android:id="@+id/home"
- style="@style/NavigationBarButton"
- systemui:intent="intent:#Intent;action=android.intent.action.MAIN;category=android.intent.category.HOME;launchFlags=0x14000000;end"
- android:src="@drawable/car_ic_overview"
- android:background="?android:attr/selectableItemBackground"
- />
-
- <com.android.systemui.statusbar.car.CarFacetButton
- android:id="@+id/maps_nav"
- style="@style/NavigationBarButton"
- systemui:icon="@drawable/car_ic_navigation"
- systemui:intent="intent:#Intent;component=com.android.car.mapsplaceholder/.MapsPlaceholderActivity;launchFlags=0x24000000;end"
- systemui:componentNames="com.android.car.mapsplaceholder/.MapsPlaceholderActivity"
- />
-
- <com.android.systemui.statusbar.car.CarFacetButton
- android:id="@+id/music_nav"
- style="@style/NavigationBarButton"
- systemui:icon="@drawable/car_ic_music"
- systemui:intent="intent:#Intent;component=com.android.car.media/.MediaActivity;launchFlags=0x14000000;end"
- systemui:packages="com.android.car.media"
- />
-
- <com.android.systemui.statusbar.car.CarFacetButton
- android:id="@+id/phone_nav"
- style="@style/NavigationBarButton"
- systemui:icon="@drawable/car_ic_phone"
- systemui:intent="intent:#Intent;component=com.android.car.dialer/.TelecomActivity;launchFlags=0x14000000;end"
- systemui:componentNames="com.android.car.dialer/.TelecomActivity"
- />
-
- <com.android.systemui.statusbar.car.CarFacetButton
- android:id="@+id/grid_nav"
- style="@style/NavigationBarButton"
- systemui:icon="@drawable/car_ic_apps"
- systemui:intent="intent:#Intent;component=com.android.car.carlauncher/.AppGridActivity;launchFlags=0x24000000;end"
- systemui:componentNames="com.android.car.carlauncher/.AppGridActivity"
- />
-
- <Space
- android:layout_height="match_parent"
- android:layout_width="0dp"
- android:layout_weight="1"/>
-
- <com.android.systemui.statusbar.car.CarNavigationButton
- android:id="@+id/hvac"
- style="@style/NavigationBarButton"
- systemui:intent="intent:#Intent;action=android.car.intent.action.TOGGLE_HVAC_CONTROLS;end"
- systemui:broadcast="true"
- android:src="@drawable/car_ic_hvac"
- android:background="?android:attr/selectableItemBackground"
- />
-
- <com.android.keyguard.AlphaOptimizedImageButton
- android:id="@+id/notifications"
- style="@style/NavigationBarButton"
- android:src="@drawable/car_ic_notification"
- android:background="?android:attr/selectableItemBackground"
- />
-
- <FrameLayout
- android:id="@+id/clock_container"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:layout_centerInParent="true"
- >
- <com.android.systemui.statusbar.car.CarNavigationButton
- android:id="@+id/qs"
- android:layout_height="match_parent"
- android:layout_width="match_parent"
- android:background="@null"
- systemui:intent="intent:#Intent;component=com.android.car.settings/.common.CarSettingActivity;launchFlags=0x14008000;end"
- />
- <com.android.systemui.statusbar.policy.Clock
- android:id="@+id/clock"
- android:textAppearance="@style/TextAppearance.StatusBar.Clock"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:singleLine="true"
- android:paddingStart="@dimen/status_bar_clock_starting_padding"
- android:paddingEnd="@dimen/status_bar_clock_end_padding"
- android:gravity="center_vertical"
- />
- </FrameLayout>
- </LinearLayout>
-
- <LinearLayout
- android:layout_height="match_parent"
- android:layout_width="wrap_content"
- android:gravity="center"
- android:paddingStart="@dimen/car_keyline_1"
- android:paddingEnd="@dimen/car_keyline_1"
- android:id="@+id/lock_screen_nav_buttons"
- android:layout_weight="1"
- android:visibility="gone">
-
- <Space
- android:layout_height="match_parent"
- android:layout_width="0dp"
- android:layout_weight="1"/>
-
- <com.android.systemui.statusbar.car.CarNavigationButton
- android:id="@+id/hvac_lockscreen"
- style="@style/NavigationBarButton"
- systemui:intent="intent:#Intent;action=android.car.intent.action.TOGGLE_HVAC_CONTROLS;end"
- systemui:broadcast="true"
- android:src="@drawable/car_ic_hvac"
- android:background="?android:attr/selectableItemBackground"
- />
-
- <Space
- style="@style/NavigationBarButton"/>
-
- <com.android.systemui.statusbar.policy.Clock
- android:id="@+id/clock_lockscreen"
- android:textAppearance="@style/TextAppearance.StatusBar.Clock"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:singleLine="true"
- android:paddingStart="@dimen/status_bar_clock_starting_padding"
- android:paddingEnd="@dimen/status_bar_clock_end_padding"
- android:gravity="center_vertical"
- />
- </LinearLayout>
-
-</com.android.systemui.statusbar.car.CarNavigationBarView>
-
diff --git a/car_product/overlay/frameworks/base/packages/SystemUI/res/layout/status_bar.xml b/car_product/overlay/frameworks/base/packages/SystemUI/res/layout/status_bar.xml
deleted file mode 100644
index b99bfe8..0000000
--- a/car_product/overlay/frameworks/base/packages/SystemUI/res/layout/status_bar.xml
+++ /dev/null
@@ -1,91 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-**
-** Copyright 2006, 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.
-*/
--->
-
-<com.android.systemui.statusbar.phone.PhoneStatusBarView
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:systemui="http://schemas.android.com/apk/res/com.android.systemui"
- android:id="@+id/status_bar"
- android:layout_width="match_parent"
- android:layout_height="@dimen/status_bar_height"
- android:background="@drawable/system_bar_background"
- android:orientation="vertical"
- android:focusable="false"
- android:descendantFocusability="afterDescendants"
- >
-
- <ImageView
- android:id="@+id/notification_lights_out"
- android:layout_width="@dimen/status_bar_icon_size"
- android:layout_height="match_parent"
- android:paddingStart="6dip"
- android:paddingBottom="2dip"
- android:src="@drawable/ic_sysbar_lights_out_dot_small"
- android:scaleType="center"
- android:visibility="gone"
- />
-
- <LinearLayout android:id="@+id/status_bar_contents"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:paddingStart="6dp"
- android:paddingEnd="8dp"
- android:orientation="horizontal"
- >
-
- <include layout="@layout/heads_up_status_bar_layout" />
-
- <!-- The alpha of this area is controlled from both PhoneStatusBarTransitions and
- PhoneStatusBar (DISABLE_NOTIFICATION_ICONS). -->
- <com.android.systemui.statusbar.AlphaOptimizedFrameLayout
- android:id="@+id/notification_icon_area"
- android:layout_width="0dip"
- android:layout_height="match_parent"
- android:layout_weight="1"
- android:orientation="horizontal"
- android:visibility="gone" />
-
- <com.android.keyguard.AlphaOptimizedLinearLayout android:id="@+id/system_icon_area"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="horizontal"
- >
-
- <include layout="@layout/system_icons" />
-
- <!-- Sort of a crude hack but we can't do much here without refactoring
- system ui code. -->
- <Space
- android:layout_width="0dp"
- android:layout_height="match_parent"
- android:layout_weight="1" />
-
- <com.android.systemui.statusbar.policy.Clock
- android:id="@+id/clock"
- android:textAppearance="@style/TextAppearance.StatusBar.Clock"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:singleLine="true"
- android:paddingStart="@dimen/status_bar_clock_starting_padding"
- android:paddingEnd="@dimen/status_bar_clock_end_padding"
- android:gravity="center_vertical|end"
- />
- </com.android.keyguard.AlphaOptimizedLinearLayout>
- </LinearLayout>
-
-</com.android.systemui.statusbar.phone.PhoneStatusBarView>
diff --git a/car_product/overlay/frameworks/base/packages/SystemUI/res/values-night/colors.xml b/car_product/overlay/frameworks/base/packages/SystemUI/res/values-night/colors.xml
deleted file mode 100644
index 26479a5..0000000
--- a/car_product/overlay/frameworks/base/packages/SystemUI/res/values-night/colors.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2016, 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>
- <color name="status_bar_background_color">#ff000000</color>
- <color name="system_bar_background_opaque">#ff0c1013</color>
-
- <!-- The color of the ripples on the untinted notifications -->
- <color name="notification_ripple_untinted_color">@color/ripple_material_dark</color>
-</resources>
diff --git a/car_product/overlay/frameworks/base/packages/SystemUI/res/values-sw720dp/dimens.xml b/car_product/overlay/frameworks/base/packages/SystemUI/res/values-sw720dp/dimens.xml
deleted file mode 100644
index 3ab2968..0000000
--- a/car_product/overlay/frameworks/base/packages/SystemUI/res/values-sw720dp/dimens.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2016, 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>
- <!-- gap on either side of status bar notification icons -->
- <dimen name="status_bar_icon_padding">8dp</dimen>
-</resources>
diff --git a/car_product/overlay/frameworks/base/packages/SystemUI/res/values/arrays_car.xml b/car_product/overlay/frameworks/base/packages/SystemUI/res/values/arrays_car.xml
deleted file mode 100644
index 1fa0b3b..0000000
--- a/car_product/overlay/frameworks/base/packages/SystemUI/res/values/arrays_car.xml
+++ /dev/null
@@ -1,62 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-**
-** Copyright 2016, 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>
- <!-- There needs to be correspondence per index between these arrays, which means that if there
- isn't a longpress action associated with a shortcut item, put in an empty item to make
- sure everything lines up.
- -->
- <array name="car_facet_icons">
- <item>@drawable/car_ic_navigation</item>
- <item>@drawable/car_ic_phone</item>
- <item>@drawable/car_ic_overview</item>
- <item>@drawable/car_ic_music</item>
- <item>@drawable/car_ic_car</item>
- </array>
- <array name="car_facet_intent_uris">
- <!-- Launch the lenspicker for all the facets. The lens picker will trampoline into the last run app or display a list of valid apps -->
- <item>intent:#Intent;action=android.intent.action.MAIN;category=android.intent.category.LAUNCHER;launchFlags=0x14000000;package=com.android.support.car.lenspicker;end</item>
- <item>intent:#Intent;action=android.intent.action.MAIN;category=android.intent.category.LAUNCHER;launchFlags=0x14000000;package=com.android.support.car.lenspicker;end</item>
- <item>intent:#Intent;action=android.intent.action.MAIN;category=android.intent.category.HOME;launchFlags=0x14000000;S.system_command=toggle_notifications;end</item>
- <item>intent:#Intent;action=android.intent.action.MAIN;category=android.intent.category.LAUNCHER;launchFlags=0x14000000;package=com.android.support.car.lenspicker;end</item>
- <item>intent:#Intent;action=android.intent.action.MAIN;category=android.intent.category.LAUNCHER;launchFlags=0x14000000;package=com.android.support.car.lenspicker;end</item>
- </array>
- <array name="car_facet_longpress_intent_uris">
- <item></item>
- <item></item>
- <item></item>
- <item></item>
- <!-- Long pressing the overflow triggers a bug report -->
- <item>intent:#Intent;component=com.google.android.car.bugreport/.BugReportActivity;end</item>
- </array>
- <array name="car_facet_category_filters">
- <item>android.intent.category.APP_MAPS</item>
- <item>android.intent.category.APP_MESSAGING</item>
- <item></item>
- <item>android.intent.category.APP_MUSIC</item>
- <item></item>
- </array>
- <array name="car_facet_package_filters">
- <item>com.android.car.mapsplaceholder</item>
- <item>com.android.car.dialer</item>
- <item>com.android.car.overview</item>
- <item></item>
- <item>com.android.car.hvac;com.android.settings;com.android.car.settings;com.android.vending;com.google.android.car.bugreport;com.google.android.car.kitchensink;com.android.car.systemupdater;org.chromium.webview_shell;com.android.contacts;org.codeaurora.bluetooth.bttestapp;com.google.android.projection.sink;com.google.android.googlequicksearchbox</item>
- </array>
-</resources>
diff --git a/car_product/overlay/frameworks/base/packages/SystemUI/res/values/colors.xml b/car_product/overlay/frameworks/base/packages/SystemUI/res/values/colors.xml
deleted file mode 100644
index 30c0c58..0000000
--- a/car_product/overlay/frameworks/base/packages/SystemUI/res/values/colors.xml
+++ /dev/null
@@ -1,43 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 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.
-*/
--->
-<resources>
- <!-- System ui can't depend on car libs so redefine. -->
- <color name="car_grey_50">#fffafafa</color>
-
- <color name="docked_divider_background">@color/car_grey_50</color>
- <color name="system_bar_background_opaque">#ff172026</color>
-
- <color name="status_bar_background_color">#33000000</color>
- <drawable name="system_bar_background">@color/status_bar_background_color</drawable>
-
- <!-- The scrim color for the background of the notifications shade. -->
- <color name="scrim_behind_color">#172026</color>
-
- <!-- The color of the dividing line between grouped notifications. -->
- <color name="notification_divider_color">@*android:color/notification_action_list</color>
-
- <!-- The color of the ripples on the untinted notifications -->
- <color name="notification_ripple_untinted_color">@color/ripple_material_light</color>
-
- <color name="car_teal_700">#ff00796b</color>
- <color name="car_grey_300">#ffe0e0e0</color>
- <color name="car_grey_900">#ff212121</color>
-
- <color name="keyguard_button_text_color">@android:color/black</color>
-</resources>
diff --git a/car_product/overlay/frameworks/base/packages/SystemUI/res/values/config.xml b/car_product/overlay/frameworks/base/packages/SystemUI/res/values/config.xml
index e48a06a..d8d8516 100644
--- a/car_product/overlay/frameworks/base/packages/SystemUI/res/values/config.xml
+++ b/car_product/overlay/frameworks/base/packages/SystemUI/res/values/config.xml
@@ -19,9 +19,6 @@
<!-- Resource overrides for car system ui. -->
<resources>
- <string name="config_statusBarComponent" translatable="false">com.android.systemui.statusbar.car.CarStatusBar</string>
- <string name="config_systemUIFactoryComponent" translatable="false">com.android.systemui.car.CarSystemUIFactory</string>
- <bool name="config_enableFullscreenUserSwitcher">true</bool>
<!-- Notifications on the car should not show the gear icon. Swiping should only dismiss the
cards. -->
diff --git a/car_product/overlay/frameworks/base/packages/SystemUI/res/values/config_car.xml b/car_product/overlay/frameworks/base/packages/SystemUI/res/values/config_car.xml
deleted file mode 100644
index 9c8dcb1..0000000
--- a/car_product/overlay/frameworks/base/packages/SystemUI/res/values/config_car.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2016, 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>
- <!-- These next two work together, if you enable this first one you need to provide an intent
- uri that will be launched into the docked window. -->
- <bool name="config_enablePersistentDockedActivity">false</bool>
- <string name="config_persistentDockedActivityIntentUri" translatable="false"></string>
-</resources>
diff --git a/car_product/overlay/frameworks/base/packages/SystemUI/res/values/dimens.xml b/car_product/overlay/frameworks/base/packages/SystemUI/res/values/dimens.xml
index 37a6238..b57fcb9 100644
--- a/car_product/overlay/frameworks/base/packages/SystemUI/res/values/dimens.xml
+++ b/car_product/overlay/frameworks/base/packages/SystemUI/res/values/dimens.xml
@@ -21,56 +21,6 @@
scrim has no transparency. -->
<item name="scrim_behind_alpha" format="float" type="dimen">1.0</item>
- <!-- The amount by which to scale up the status bar icons. -->
- <item name="status_bar_icon_scale_factor" format="float" type="dimen">2.3</item>
-
- <!-- The font size for the clock in the status bar. -->
- <dimen name="status_bar_clock_size">24sp</dimen>
-
- <!-- The starting padding for the clock in the status bar. -->
- <dimen name="status_bar_clock_starting_padding">12dp</dimen>
-
- <!-- The end padding for the clock in the status bar. -->
- <dimen name="status_bar_clock_end_padding">@dimen/status_bar_clock_starting_padding</dimen>
-
- <!-- size at which Notification icons will be drawn in the status bar -->
- <dimen name="status_bar_icon_drawing_size">32dp</dimen>
-
- <!-- Starting margin before the signal cluster -->
- <dimen name="signal_cluster_margin_start">8dp</dimen>
-
- <!-- Padding between signal cluster and battery icon -->
- <dimen name="signal_cluster_battery_padding">@dimen/status_bar_clock_starting_padding</dimen>
-
- <!-- Spacing after the wifi signals that is present if there are any icons following it. -->
- <dimen name="status_bar_wifi_signal_spacer_width">@dimen/status_bar_clock_starting_padding</dimen>
-
- <!-- Spacing before the airplane mode icon if there are any icons preceding it. -->
- <dimen name="status_bar_airplane_spacer_width">@dimen/status_bar_clock_starting_padding</dimen>
-
- <!-- Padding at the end of the view that displays the mobile signal icons. This value should
- be double the signal_cluster_margin_start. -->
- <dimen name="mobile_signal_group_end_padding">16dp</dimen>
-
- <!-- Padding between the mobile data type and the strength indicator. -->
- <dimen name="mobile_data_icon_start_padding">@dimen/mobile_signal_group_end_padding</dimen>
-
- <!-- gap on either side of status bar notification icons -->
- <dimen name="status_bar_icon_padding">8dp</dimen>
-
- <!-- Standard image button size for volume dialog buttons -->
- <dimen name="volume_button_size">84dp</dimen>
-
- <!-- The maximum width allowed for the volume dialog. For auto, we allow this to span a good
- deal of the screen. This value accounts for the side margins. -->
- <dimen name="volume_dialog_panel_width">1920dp</dimen>
-
- <dimen name="car_navigation_button_width">56dp</dimen>
- <dimen name="car_navigation_button_holder_width">96dp</dimen>
-
- <dimen name="navigation_bar_padding_top">0dp</dimen>
- <dimen name="navigation_bar_padding_side">264dp</dimen>
-
<!-- Largest size an avatar might need to be drawn in the user picker, status bar, or
quick settings header -->
<dimen name="max_avatar_size">128dp</dimen>
@@ -141,18 +91,4 @@
etc. in the car setting.-->
<dimen name="qs_footer_height">74dp</dimen>
- <dimen name="volume_dialog_side_margin">@dimen/side_margin</dimen>
-
- <dimen name="volume_dialog_elevation">6dp</dimen>
-
- <dimen name="volume_dialog_row_margin_end">@dimen/car_keyline_3</dimen>
-
- <dimen name="volume_dialog_row_padding_end">0dp</dimen>
-
- <dimen name="line_item_height">128dp</dimen>
- <dimen name="volume_icon_size">96dp</dimen>
- <dimen name="side_margin">148dp</dimen>
- <dimen name="car_keyline_1">24dp</dimen>
- <dimen name="car_keyline_2">96dp</dimen>
- <dimen name="car_keyline_3">128dp</dimen>
</resources>
diff --git a/car_product/overlay/frameworks/base/packages/SystemUI/res/values/styles.xml b/car_product/overlay/frameworks/base/packages/SystemUI/res/values/styles.xml
deleted file mode 100644
index 68fc641..0000000
--- a/car_product/overlay/frameworks/base/packages/SystemUI/res/values/styles.xml
+++ /dev/null
@@ -1,37 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2016, 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:android="http://schemas.android.com/apk/res/android">
-
- <!-- The style for the volume icons in the volume dialog. This style makes the icon scale to
- fit its container since auto wants the icon to be larger. The padding is added to make it
- so the icon does not press along the edges of the dialog. -->
- <style name="VolumeButtons" parent="@android:style/Widget.Material.Button.Borderless">
- <item name="android:background">@drawable/btn_borderless_rect</item>
- <item name="android:scaleType">fitCenter</item>
- <item name="android:padding">22dp</item>
- </style>
-
- <style name="NavigationBarButton">
- <item name="android:layout_height">56dp</item>
- <item name="android:layout_width">76dp</item>
- <item name="android:paddingStart">@dimen/car_padding_1</item>
- <item name="android:paddingEnd">@dimen/car_padding_1</item>
- </style>
-
-</resources>
diff --git a/car_product/overlay/packages/apps/PackageInstaller/res/drawable/ic_check_box.xml b/car_product/overlay/packages/apps/PackageInstaller/res/drawable/ic_check_box.xml
new file mode 100644
index 0000000..e985f39
--- /dev/null
+++ b/car_product/overlay/packages/apps/PackageInstaller/res/drawable/ic_check_box.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2018 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
+ -->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android" >
+ <item android:drawable="@drawable/ic_check_box_unchecked"
+ android:state_checked="false"/>
+ <item android:drawable="@drawable/ic_check_box_checked"
+ android:state_checked="true"/>
+ <item android:drawable="@drawable/ic_check_box_unchecked"/>
+</selector>
diff --git a/car_product/overlay/packages/apps/PackageInstaller/res/drawable/ic_check_box_checked.xml b/car_product/overlay/packages/apps/PackageInstaller/res/drawable/ic_check_box_checked.xml
new file mode 100644
index 0000000..1aeae8b
--- /dev/null
+++ b/car_product/overlay/packages/apps/PackageInstaller/res/drawable/ic_check_box_checked.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2018 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
+ -->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="@dimen/car_primary_icon_size"
+ android:height="@dimen/car_primary_icon_size"
+ android:tint="@color/car_teal_700"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:pathData="M19,3L5,3c-1.11,0 -2,0.9 -2,2v14c0,1.1 0.89,2 2,2h14c1.11,0 2,-0.9 2,-2L21,5c0,-1.1 -0.89,-2 -2,-2zM10,17l-5,-5 1.41,-1.41L10,14.17l7.59,-7.59L19,8l-9,9z"
+ android:fillColor="#000000"/>
+</vector>
diff --git a/car_product/overlay/packages/apps/PackageInstaller/res/drawable/ic_check_box_unchecked.xml b/car_product/overlay/packages/apps/PackageInstaller/res/drawable/ic_check_box_unchecked.xml
new file mode 100644
index 0000000..0b2b5be
--- /dev/null
+++ b/car_product/overlay/packages/apps/PackageInstaller/res/drawable/ic_check_box_unchecked.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2018 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
+ -->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="@dimen/car_primary_icon_size"
+ android:height="@dimen/car_primary_icon_size"
+ android:tint="@color/car_tint"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:pathData="M19,5v14H5V5h14m0,-2H5c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h14c1.1,0 2,-0.9 2,-2V5c0,-1.1 -0.9,-2 -2,-2z"
+ android:fillColor="#000000"/>
+</vector>
diff --git a/car_product/overlay/packages/apps/PackageInstaller/res/layout/grant_permissions.xml b/car_product/overlay/packages/apps/PackageInstaller/res/layout/grant_permissions.xml
index 08e5fd8..450148e 100644
--- a/car_product/overlay/packages/apps/PackageInstaller/res/layout/grant_permissions.xml
+++ b/car_product/overlay/packages/apps/PackageInstaller/res/layout/grant_permissions.xml
@@ -58,7 +58,7 @@
android:button="@drawable/ic_check_box"
android:text="@string/never_ask_again"
android:textColor="?android:attr/textColorSecondary"
- android:textSize="@dimen/car_action1_size"
+ android:textSize="@dimen/car_body3_size"
android:visibility="gone">
</CheckBox>
@@ -80,7 +80,7 @@
android:paddingEnd="@dimen/car_padding_4"
android:text="@string/grant_dialog_button_deny"
android:textColor="@color/car_highlight"
- android:textSize="@dimen/car_action1_size"
+ android:textSize="@dimen/car_body3_size"
android:textStyle="bold">
</Button>
@@ -93,7 +93,7 @@
android:paddingEnd="@dimen/car_padding_4"
android:text="@string/grant_dialog_button_allow"
android:textColor="@color/car_highlight"
- android:textSize="@dimen/car_action1_size"
+ android:textSize="@dimen/car_body3_size"
android:textStyle="bold">
</Button>
diff --git a/car_product/overlay/packages/apps/PackageInstaller/res/values/colors.xml b/car_product/overlay/packages/apps/PackageInstaller/res/values/colors.xml
new file mode 100644
index 0000000..2b22b78
--- /dev/null
+++ b/car_product/overlay/packages/apps/PackageInstaller/res/values/colors.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2018 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>
+ <color name="car_highlight_light">@color/car_teal_700</color>
+ <color name="car_highlight_dark">@color/car_teal_200</color>
+ <color name="car_highlight">@color/car_highlight_light</color>
+</resources>
diff --git a/service/AndroidManifest.xml b/service/AndroidManifest.xml
index 24c9cd7..4a16579 100644
--- a/service/AndroidManifest.xml
+++ b/service/AndroidManifest.xml
@@ -129,6 +129,11 @@
android:label="@string/car_permission_label_control_car_exterior_lights"
android:description="@string/car_permission_desc_control_car_exterior_lights" />
<permission
+ android:name="android.car.permission.CAR_POWER"
+ android:protectionLevel="system|signature"
+ android:label="@string/car_permission_label_car_power"
+ android:description="@string/car_permission_desc_car_power" />
+ <permission
android:name="android.car.permission.CAR_POWERTRAIN"
android:protectionLevel="normal"
android:label="@string/car_permission_label_car_powertrain"
diff --git a/service/res/values/strings.xml b/service/res/values/strings.xml
index 1947e43..c87561d 100644
--- a/service/res/values/strings.xml
+++ b/service/res/values/strings.xml
@@ -202,4 +202,9 @@
<string name="car_permission_label_car_powertrain">Car Powertrain</string>
<!-- Permission text: apps read information of car's powertrain [CHAR LIMIT=NONE] -->
<string name="car_permission_desc_car_powertrain">Access car powertrain information</string>
+
+ <!-- Permission text: apps read information of car's power state [CHAR LIMIT=NONE] -->
+ <string name="car_permission_label_car_power">Car Power</string>
+ <!-- Permission text: apps read information of car's power state [CHAR LIMIT=NONE] -->
+ <string name="car_permission_desc_car_power">Access car power state</string>
</resources>
diff --git a/service/src/com/android/car/CarInputService.java b/service/src/com/android/car/CarInputService.java
index 2b97221..c95674e 100644
--- a/service/src/com/android/car/CarInputService.java
+++ b/service/src/com/android/car/CarInputService.java
@@ -16,7 +16,7 @@
package com.android.car;
import static android.hardware.input.InputManager.INJECT_INPUT_EVENT_MODE_ASYNC;
-import static android.service.voice.VoiceInteractionSession.SHOW_SOURCE_ASSIST_GESTURE;
+import static android.service.voice.VoiceInteractionSession.SHOW_SOURCE_PUSH_TO_TALK;
import android.app.ActivityManager;
import android.car.input.CarInputHandlingService;
@@ -355,7 +355,7 @@
args.putBoolean(EXTRA_CAR_PUSH_TO_TALK, true);
mAssistUtils.showSessionForActiveService(args,
- SHOW_SOURCE_ASSIST_GESTURE, mShowCallback, null /*activityToken*/);
+ SHOW_SOURCE_PUSH_TO_TALK, mShowCallback, null /*activityToken*/);
}
private void handleInstrumentClusterKey(KeyEvent event) {
diff --git a/service/src/com/android/car/CarPowerManagementService.java b/service/src/com/android/car/CarPowerManagementService.java
index 57ccf62..c42899a 100644
--- a/service/src/com/android/car/CarPowerManagementService.java
+++ b/service/src/com/android/car/CarPowerManagementService.java
@@ -126,6 +126,7 @@
private PowerHandler mHandler;
private int mBootReason;
private boolean mShutdownOnNextSuspend = false;
+ private int mNextWakeupSec;
// TODO: Make this OEM configurable.
private final static int APP_EXTEND_MAX_MS = 10000;
@@ -424,14 +425,14 @@
processingTimeMs += sendPowerManagerEvent(shuttingDown);
if (processingTimeMs > 0) {
int pollingCount = (int)(processingTimeMs / SHUTDOWN_POLLING_INTERVAL_MS) + 1;
- Log.i(CarLog.TAG_POWER, "processing before shutdown expected for :" + processingTimeMs +
- " ms, adding polling:" + pollingCount);
+ Log.i(CarLog.TAG_POWER, "processing before shutdown expected for: "
+ + processingTimeMs + " ms, adding polling:" + pollingCount);
synchronized (this) {
mProcessingStartTime = SystemClock.elapsedRealtime();
releaseTimerLocked();
mTimer = new Timer();
- mTimer.scheduleAtFixedRate(new ShutdownProcessingTimerTask(shuttingDown,
- pollingCount),
+ mTimer.scheduleAtFixedRate(
+ new ShutdownProcessingTimerTask(shuttingDown, pollingCount),
0 /*delay*/,
SHUTDOWN_POLLING_INTERVAL_MS);
}
@@ -464,7 +465,8 @@
}
mPowerManagerListeners.finishBroadcast();
if (!mPowerManagerListenerTokens.isEmpty()) {
- Log.i(CarLog.TAG_POWER, "mPowerMangerListenerTokens not empty, add APP_EXTEND_MAX_MS");
+ Log.i(CarLog.TAG_POWER,
+ "mPowerMangerListenerTokens not empty, add APP_EXTEND_MAX_MS");
processingTimeMs += APP_EXTEND_MAX_MS;
}
}
@@ -483,16 +485,18 @@
for (PowerServiceEventListener listener : mListeners) {
listener.onSleepEntry();
}
- int wakeupTimeSec = getWakeupTime();
mHal.sendSleepEntry();
synchronized (this) {
mLastSleepEntryTime = SystemClock.elapsedRealtime();
}
- if (mSystemInterface.enterDeepSleep(wakeupTimeSec) == false) {
+ if (!mSystemInterface.enterDeepSleep(mNextWakeupSec)) {
// System did not suspend. Need to shutdown
// TODO: Shutdown gracefully
Log.e(CarLog.TAG_POWER, "Sleep did not succeed. Need to shutdown");
}
+ // When we wake up, we reset the next wake up time and if no one will set it
+ // System will suspend / shutdown forever.
+ mNextWakeupSec = 0;
mHal.sendSleepExit();
for (PowerServiceEventListener listener : mListeners) {
listener.onSleepExit();
@@ -551,25 +555,10 @@
for (PowerServiceEventListener listener : mListeners) {
listener.onShutdown();
}
- int wakeupTimeSec = 0;
- if (mHal.isTimedWakeupAllowed()) {
- wakeupTimeSec = getWakeupTime();
- }
- mHal.sendShutdownStart(wakeupTimeSec);
+ mHal.sendShutdownStart(mHal.isTimedWakeupAllowed() ? mNextWakeupSec : 0);
mSystemInterface.shutdown();
}
- private int getWakeupTime() {
- int wakeupTimeSec = 0;
- for (PowerEventProcessingHandlerWrapper wrapper : mPowerEventProcessingHandlers) {
- int t = wrapper.handler.getWakeupTime();
- if (t > wakeupTimeSec) {
- wakeupTimeSec = t;
- }
- }
- return wakeupTimeSec;
- }
-
private void doHandleProcessingComplete(boolean shutdownWhenCompleted) {
synchronized (this) {
releaseTimerLocked();
@@ -676,6 +665,20 @@
}
}
+ @Override
+ public synchronized void scheduleNextWakeupTime(int seconds) {
+ if (seconds < 0) {
+ Log.w(CarLog.TAG_POWER, "Next wake up can not be in negative time. Ignoring!");
+ return;
+ }
+ if (mNextWakeupSec == 0 || mNextWakeupSec > seconds) {
+ mNextWakeupSec = seconds;
+ } else {
+ Log.d(CarLog.TAG_POWER, "Tried to schedule next wake up, but already had shorter "
+ + " scheduled time");
+ }
+ }
+
private void finishedLocked(IBinder binder, int token) {
int currentToken = mPowerManagerListenerTokens.get(binder);
if (currentToken == token) {
@@ -683,7 +686,8 @@
if (mPowerManagerListenerTokens.isEmpty() &&
(mCurrentState.mState == PowerHalService.STATE_SHUTDOWN_PREPARE)) {
// All apps are ready to shutdown/suspend.
- Log.i(CarLog.TAG_POWER, "Apps are finished, call notifyPowerEventProcessingCompletion");
+ Log.i(CarLog.TAG_POWER,
+ "Apps are finished, call notifyPowerEventProcessingCompletion");
notifyPowerEventProcessingCompletion(null);
}
}
diff --git a/service/src/com/android/car/DeviceIdleControllerWrapper.java b/service/src/com/android/car/DeviceIdleControllerWrapper.java
deleted file mode 100644
index 0ed1b78..0000000
--- a/service/src/com/android/car/DeviceIdleControllerWrapper.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright (C) 2016 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;
-
-import android.os.Handler;
-import android.os.Message;
-import android.util.Log;
-
-import com.android.internal.annotations.GuardedBy;
-import com.android.internal.annotations.VisibleForTesting;
-
-import java.lang.ref.WeakReference;
-
-/**
-* An wrapper class that can be backed by a real DeviceIdleController or a mocked one.
-*/
-public abstract class DeviceIdleControllerWrapper {
- private static final String TAG = "Garage_DeviceIdleWrapper";
-
- private static final int MSG_REPORT_ACTIVE = 1;
-
- @VisibleForTesting
- protected WeakReference<DeviceMaintenanceActivityListener> mListener;
-
- public interface DeviceMaintenanceActivityListener {
- public void onMaintenanceActivityChanged(boolean active);
- }
- private final Object mLock = new Object();
- @GuardedBy("mLock")
- private boolean mActive;
-
- private Handler mHandler = new IdleControllerHandler();
-
- private class IdleControllerHandler extends Handler {
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case MSG_REPORT_ACTIVE:
- boolean active = msg.arg1 == 1;
- if (mListener.get() != null) {
- mListener.get().onMaintenanceActivityChanged(active);
- }
- break;
- }
- }
- }
-
- public boolean startTracking(DeviceMaintenanceActivityListener listener) {
- synchronized (mLock) {
- mListener = new WeakReference<DeviceMaintenanceActivityListener>(listener);
- mActive = startLocked();
- return mActive;
- }
- }
-
- protected abstract boolean startLocked();
-
- public abstract void stopTracking();
-
- @VisibleForTesting
- protected void reportActiveLocked(final boolean active) {
- // post to a handler instead of calling the callback directly to avoid potential deadlock.
- mHandler.sendMessage(mHandler.obtainMessage(MSG_REPORT_ACTIVE, active ? 1 : 0, 0));
- }
-
- @VisibleForTesting
- protected void setMaintenanceActivity(final boolean active) {
- synchronized (mLock) {
- if (mActive == active) {
- return;
- }
- mActive = active;
-
- if (mListener.get() == null) {
- // do cleanup if the listener has gone and did not call release.
- stopTracking();
- return;
- }
- reportActiveLocked(active);
- }
- }
-}
diff --git a/service/src/com/android/car/ICarImpl.java b/service/src/com/android/car/ICarImpl.java
index 67c50a7..a99a107 100644
--- a/service/src/com/android/car/ICarImpl.java
+++ b/service/src/com/android/car/ICarImpl.java
@@ -122,7 +122,7 @@
mSystemActivityMonitoringService);
mCarInputService = new CarInputService(serviceContext, mHal.getInputHal());
mCarProjectionService = new CarProjectionService(serviceContext, mCarInputService);
- mGarageModeService = new GarageModeService(mContext, mCarPowerManagementService);
+ mGarageModeService = new GarageModeService(mContext);
mAppFocusService = new AppFocusService(serviceContext, mSystemActivityMonitoringService);
mCarAudioService = new CarAudioService(serviceContext);
mCarNightService = new CarNightService(serviceContext, mCarPropertyService);
@@ -167,12 +167,9 @@
allServices.add(mCarConfigurationService);
allServices.add(mVmsSubscriberService);
allServices.add(mVmsPublisherService);
-
if (mUserManagerHelper.isHeadlessSystemUser()) {
- mCarUserService = new CarUserService(serviceContext, mUserManagerHelper);
- allServices.add(mCarUserService);
+ allServices.add(new CarUserService(serviceContext, mUserManagerHelper));
}
-
allServices.add(mCarLocationService);
mAllServices = allServices.toArray(new CarServiceBase[allServices.size()]);
}
@@ -563,10 +560,10 @@
private void forceGarageMode(String arg, PrintWriter writer) {
switch (arg) {
case PARAM_ON_MODE:
- mGarageModeService.onPrepareShutdown(false);
+ mGarageModeService.forceStartGarageMode();
break;
case PARAM_OFF_MODE:
- mGarageModeService.onSleepEntry();
+ mGarageModeService.stopAndResetGarageMode();
break;
case PARAM_QUERY_MODE:
// Nothing to do. Always query at the end anyway.
@@ -576,7 +573,7 @@
+ PARAM_OFF_MODE + "|" + PARAM_QUERY_MODE);
return;
}
- writer.println("Garage mode: " + mGarageModeService.isInGarageMode());
+ writer.println("Garage mode: " + mGarageModeService.isGarageModeActive());
}
/**
diff --git a/service/src/com/android/car/VmsPublisherService.java b/service/src/com/android/car/VmsPublisherService.java
index a240e17..84eb8ce 100644
--- a/service/src/com/android/car/VmsPublisherService.java
+++ b/service/src/com/android/car/VmsPublisherService.java
@@ -105,6 +105,8 @@
mContext.registerReceiver(mBootCompleteReceiver,
new IntentFilter(Intent.ACTION_LOCKED_BOOT_COMPLETED));
}
+ // Signal to publishers that the PublisherService is ready.
+ mHal.signalPublisherServiceIsReady();
}
private void bindToAllPublishers() {
@@ -308,9 +310,8 @@
}
private boolean isTestEnvironment() {
- // If the context is derived from other package it means we're running under
- // environment.
- return !TextUtils.equals(mContext.getBasePackageName(), mContext.getPackageName());
+ // If the context has "test" in it.
+ return mContext.getBasePackageName().contains("test");
}
class PublisherConnection implements ServiceConnection {
diff --git a/service/src/com/android/car/VmsSubscriberService.java b/service/src/com/android/car/VmsSubscriberService.java
index c4c507e..213757c 100644
--- a/service/src/com/android/car/VmsSubscriberService.java
+++ b/service/src/com/android/car/VmsSubscriberService.java
@@ -124,18 +124,20 @@
public void add(IVmsSubscriberClient subscriber) {
ICarImpl.assertVmsSubscriberPermission(mContext);
if (subscriber == null) {
- Log.e(TAG, "register: subscriber is null.");
+ Log.e(TAG, "Trying to add a null subscriber.");
throw new IllegalArgumentException("subscriber cannot be null.");
}
- if (DBG) {
- Log.d(TAG, "register: " + subscriber);
- }
IBinder subscriberBinder = subscriber.asBinder();
synchronized (mListenerManagerLock) {
if (mSubscriberMap.containsKey(subscriberBinder)) {
- // Already registered, nothing to do.
+ if (DBG) {
+ Log.d(TAG, "Subscriber already registered: " + subscriber);
+ }
return;
}
+ if (DBG) {
+ Log.d(TAG, "Registering subscriber: " + subscriber);
+ }
ListenerDeathRecipient deathRecipient =
new ListenerDeathRecipient(subscriberBinder);
try {
@@ -203,6 +205,9 @@
@Override
public void init() {
mHal.addSubscriberListener(this);
+
+ // Signal to subscribers that the SubscriberService is ready.
+ mHal.signalSubscriberServiceIsReady();
}
@Override
diff --git a/service/src/com/android/car/garagemode/Controller.java b/service/src/com/android/car/garagemode/Controller.java
new file mode 100644
index 0000000..8fd92d1
--- /dev/null
+++ b/service/src/com/android/car/garagemode/Controller.java
@@ -0,0 +1,199 @@
+/*
+ * Copyright (C) 2018 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.garagemode;
+
+import android.app.job.JobScheduler;
+import android.car.Car;
+import android.car.CarNotConnectedException;
+import android.car.hardware.power.CarPowerManager;
+import android.car.hardware.power.CarPowerManager.CarPowerStateListener;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Looper;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.util.concurrent.CompletableFuture;
+
+/**
+ * Main controller for GarageMode. It controls all the flows of GarageMode and defines the logic.
+ */
+public class Controller implements CarPowerStateListener {
+ private static final Logger LOG = new Logger("Controller");
+
+ @VisibleForTesting final WakeupPolicy mWakeupPolicy;
+ private final GarageMode mGarageMode;
+ private final Handler mHandler;
+ private final Context mContext;
+ private final Car mCar;
+
+ private CarPowerManager mCarPowerManager;
+
+ public Controller(Context context, Looper looper) {
+ this(context, looper, null, null, null, null);
+ }
+
+ public Controller(
+ Context context,
+ Looper looper,
+ WakeupPolicy wakeupPolicy,
+ Handler handler,
+ GarageMode garageMode,
+ Car car) {
+ mContext = context;
+ mHandler = (handler == null ? new Handler(looper) : handler);
+ mWakeupPolicy =
+ (wakeupPolicy == null ? WakeupPolicy.initFromResources(context) : wakeupPolicy);
+ mGarageMode = (garageMode == null ? new GarageMode(this) : garageMode);
+ if (car == null) {
+ mCar = Car.createCar(context, new ServiceConnection() {
+ @Override
+ public void onServiceConnected(ComponentName name, IBinder service) {
+ try {
+ mCarPowerManager = (CarPowerManager) mCar.getCarManager(Car.POWER_SERVICE);
+ mCarPowerManager.setListener(Controller.this);
+ } catch (CarNotConnectedException e) {
+ LOG.e("Failed to get CarPowerManager instance", e);
+ }
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName name) {
+ if (mCarPowerManager != null) {
+ mCarPowerManager.clearListener();
+ }
+ }
+ });
+ } else {
+ mCar = car;
+ }
+ }
+
+ @Override
+ public void onStateChanged(int state, CompletableFuture<Void> future) {
+ switch (state) {
+ case CarPowerStateListener.SHUTDOWN_CANCELLED:
+ LOG.d("CPM state changed to SHUTDOWN_CANCELLED");
+ handleShutdownCancelled();
+ break;
+ case CarPowerStateListener.SHUTDOWN_ENTER:
+ LOG.d("CPM state changed to SHUTDOWN_ENTER");
+ handleShutdownEnter(future);
+ break;
+ case CarPowerStateListener.SUSPEND_ENTER:
+ LOG.d("CPM state changed to SUSPEND_ENTER");
+ handleSuspendEnter(future);
+ break;
+ case CarPowerStateListener.SUSPEND_EXIT:
+ LOG.d("CPM state changed to SUSPEND_EXIT");
+ handleSuspendExit();
+ break;
+ default:
+ }
+ }
+
+ /**
+ * @return boolean whether any jobs are currently in running that GarageMode cares about
+ */
+ boolean isGarageModeActive() {
+ return mGarageMode.isGarageModeActive();
+ }
+
+ /**
+ * Wrapper method to send a broadcast
+ *
+ * @param i intent that contains broadcast data
+ */
+ void sendBroadcast(Intent i) {
+ LOG.d("Sending broadcast with action: " + i.getAction());
+ mContext.sendBroadcast(i);
+ }
+
+ /**
+ * @return JobSchedulerService instance
+ */
+ JobScheduler getJobSchedulerService() {
+ return (JobScheduler) mContext.getSystemService(Context.JOB_SCHEDULER_SERVICE);
+ }
+
+ /**
+ * @return Handler instance used by controller
+ */
+ Handler getHandler() {
+ return mHandler;
+ }
+
+ /**
+ * Initiates GarageMode flow which will set the system idleness to true and will start
+ * monitoring jobs which has idleness constraint enabled.
+ */
+ void initiateGarageMode(CompletableFuture<Void> future) {
+ mWakeupPolicy.incrementCounter();
+ mGarageMode.enterGarageMode(future);
+ }
+
+ /**
+ * Resets GarageMode.
+ */
+ void resetGarageMode() {
+ mGarageMode.cancel();
+ mWakeupPolicy.resetCounter();
+ }
+
+ @VisibleForTesting
+ void finishGarageMode() {
+ mGarageMode.finish();
+ }
+
+ @VisibleForTesting
+ void setCarPowerManager(CarPowerManager cpm) {
+ mCarPowerManager = cpm;
+ }
+
+ void scheduleNextWakeup() {
+ if (mWakeupPolicy.getNextWakeUpInterval() <= 0) {
+ // Either there is no policy or nothing left to schedule
+ return;
+ }
+ int seconds = mWakeupPolicy.getNextWakeUpInterval();
+ try {
+ mCarPowerManager.scheduleNextWakeupTime(seconds);
+ } catch (CarNotConnectedException e) {
+ LOG.e("Car is not connected.", e);
+ }
+ }
+
+ private void handleSuspendExit() {
+ resetGarageMode();
+ }
+
+ private void handleSuspendEnter(CompletableFuture<Void> future) {
+ initiateGarageMode(future);
+ }
+
+ private void handleShutdownEnter(CompletableFuture<Void> future) {
+ initiateGarageMode(future);
+ }
+
+ private void handleShutdownCancelled() {
+ resetGarageMode();
+ }
+}
\ No newline at end of file
diff --git a/service/src/com/android/car/garagemode/GarageMode.java b/service/src/com/android/car/garagemode/GarageMode.java
new file mode 100644
index 0000000..914190d
--- /dev/null
+++ b/service/src/com/android/car/garagemode/GarageMode.java
@@ -0,0 +1,164 @@
+/*
+ * Copyright (C) 2018 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.garagemode;
+
+import android.app.job.JobInfo;
+import android.app.job.JobScheduler;
+import android.app.job.JobSnapshot;
+import android.content.Intent;
+import android.os.Handler;
+
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+
+/**
+ * Class that interacts with JobScheduler, controls system idleness and monitor jobs which are
+ * in GarageMode interest
+ */
+
+class GarageMode {
+ private static final Logger LOG = new Logger("GarageMode");
+
+ /**
+ * When changing this field value, please update
+ * {@link com.android.server.job.controllers.idle.CarIdlenessTracker} as well.
+ */
+ public static final String ACTION_GARAGE_MODE_ON =
+ "com.android.server.jobscheduler.GARAGE_MODE_ON";
+
+ /**
+ * When changing this field value, please update
+ * {@link com.android.server.job.controllers.idle.CarIdlenessTracker} as well.
+ */
+ public static final String ACTION_GARAGE_MODE_OFF =
+ "com.android.server.jobscheduler.GARAGE_MODE_OFF";
+
+ static final long JOB_SNAPSHOT_INITIAL_UPDATE_MS = 10000; // 10 seconds
+ static final long JOB_SNAPSHOT_UPDATE_FREQUENCY_MS = 1000; // 1 second
+
+ private final Controller mController;
+
+ private boolean mGarageModeActive;
+ private JobScheduler mJobScheduler;
+ private Handler mHandler;
+ private Runnable mRunnable;
+ private CompletableFuture<Void> mFuture;
+
+ GarageMode(Controller controller) {
+ mGarageModeActive = false;
+ mController = controller;
+ mJobScheduler = controller.getJobSchedulerService();
+ mHandler = controller.getHandler();
+
+ mRunnable = () -> {
+ if (areAnyIdleJobsRunning()) {
+ LOG.d("Some jobs are still running. Need to wait more ...");
+ mHandler.postDelayed(mRunnable, JOB_SNAPSHOT_UPDATE_FREQUENCY_MS);
+ } else {
+ LOG.d("No jobs are currently running.");
+ finish();
+ }
+ };
+ }
+
+ boolean isGarageModeActive() {
+ return mGarageModeActive;
+ }
+
+ void enterGarageMode(CompletableFuture<Void> future) {
+ LOG.d("Entering GarageMode");
+ synchronized (this) {
+ mGarageModeActive = true;
+ }
+ updateFuture(future);
+ broadcastSignalToJobSchedulerTo(true);
+ startMonitoringThread();
+ }
+
+ synchronized void cancel() {
+ if (mFuture != null && !mFuture.isDone()) {
+ mFuture.cancel(true);
+ }
+ mFuture = null;
+ }
+
+ synchronized void finish() {
+ mController.scheduleNextWakeup();
+ synchronized (this) {
+ if (mFuture != null && !mFuture.isDone()) {
+ mFuture.complete(null);
+ }
+ mFuture = null;
+ }
+ }
+
+ private void cleanupGarageMode() {
+ LOG.d("Cleaning up GarageMode");
+ synchronized (this) {
+ mGarageModeActive = false;
+ }
+ broadcastSignalToJobSchedulerTo(false);
+ stopMonitoringThread();
+ }
+
+ private void updateFuture(CompletableFuture<Void> future) {
+ synchronized (this) {
+ mFuture = future;
+ }
+ if (mFuture != null) {
+ mFuture.whenComplete((result, exception) -> {
+ if (exception != null) {
+ LOG.e("Seems like GarageMode got canceled, cleaning up", exception);
+ } else {
+ LOG.d("Seems like GarageMode is completed, cleaning up");
+ }
+ cleanupGarageMode();
+ });
+ }
+ }
+
+ private void broadcastSignalToJobSchedulerTo(boolean enableGarageMode) {
+ Intent i = new Intent();
+ if (enableGarageMode) {
+ i.setAction(ACTION_GARAGE_MODE_ON);
+ } else {
+ i.setAction(ACTION_GARAGE_MODE_OFF);
+ }
+ i.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_NO_ABORT);
+ mController.sendBroadcast(i);
+ }
+
+ private synchronized void startMonitoringThread() {
+ mHandler.postDelayed(mRunnable, JOB_SNAPSHOT_INITIAL_UPDATE_MS);
+ }
+
+ private synchronized void stopMonitoringThread() {
+ mHandler.removeCallbacks(mRunnable);
+ }
+
+ private boolean areAnyIdleJobsRunning() {
+ List<JobInfo> startedJobs = mJobScheduler.getStartedJobs();
+ for (JobSnapshot snap : mJobScheduler.getAllJobSnapshots()) {
+ if (startedJobs.contains(snap.getJobInfo())) {
+ if (snap.getJobInfo().isRequireDeviceIdle()) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+}
diff --git a/service/src/com/android/car/garagemode/GarageModePolicy.java b/service/src/com/android/car/garagemode/GarageModePolicy.java
deleted file mode 100644
index be7b713..0000000
--- a/service/src/com/android/car/garagemode/GarageModePolicy.java
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * Copyright (C) 2018 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.garagemode;
-
-import android.content.Context;
-import android.util.Log;
-
-import com.android.car.R;
-
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-
-/**
- * Default garage mode policy.
- *
- * The first wake up time is set to be 1am the next day. And it keeps waking up every day for a
- * week. After that, wake up every 7 days for a month, and wake up every 30 days thereafter.
- */
-public class GarageModePolicy {
- private static final String TAG = "GarageModePolicy";
- private static final Map<Character, Integer> TIME_UNITS_LOOKUP;
- static {
- TIME_UNITS_LOOKUP = new HashMap<>();
- TIME_UNITS_LOOKUP.put('m', 60);
- TIME_UNITS_LOOKUP.put('h', 3600);
- TIME_UNITS_LOOKUP.put('d', 86400);
- }
-
- private LinkedList<WakeupInterval> mWakeupIntervals;
-
- public GarageModePolicy(String[] policy) {
- mWakeupIntervals = parsePolicy(policy);
- }
-
- /**
- * Initializes GarageModePolicy from config_garageModeCadence resource array.
- * @param context to access resources
- * @return GarageModePolicy instance, created from values in resources
- */
- public static GarageModePolicy initFromResources(Context context) {
- return new GarageModePolicy(
- context.getResources().getStringArray(R.array.config_garageModeCadence));
- }
-
- /**
- * Returns the interval in milliseconds, which defines next wake up time.
- * @param index amount of times system woken up
- * @return the interval in milliseconds
- */
- public int getNextWakeUpInterval(int index) {
- if (mWakeupIntervals.size() == 0) {
- Log.e(TAG, "No wake up policy configuration was loaded.");
- return 0;
- }
-
- for (WakeupInterval wakeupTime : mWakeupIntervals) {
- if (index < wakeupTime.getNumAttempts()) {
- return wakeupTime.getWakeupInterval();
- }
- index -= wakeupTime.getNumAttempts();
- }
- Log.w(TAG, "No more garage mode wake ups scheduled; been sleeping too long.");
- return 0;
- }
-
- /**
- * Get list of {@link com.android.car.garagemode.WakeupInterval}s in this policy
- * @return list as List\<WakeupInterval\>
- */
- public List<WakeupInterval> getWakeupIntervals() {
- return mWakeupIntervals;
- }
-
- private LinkedList<WakeupInterval> parsePolicy(String[] policy) {
- LinkedList<WakeupInterval> intervals = new LinkedList<>();
- if (policy == null || policy.length == 0) {
- Log.e(TAG, "Trying to parse empty policies!");
- return intervals;
- }
-
- for (String rule : policy) {
- WakeupInterval interval = parseRule(rule);
- if (interval == null) {
- Log.e(TAG, "Invalid Policy! This rule has bad format: " + rule);
- return new LinkedList<>();
- }
- intervals.add(interval);
- }
- return intervals;
- }
-
- private WakeupInterval parseRule(String rule) {
- String[] str = rule.split(",");
-
- if (str.length != 2) {
- Log.e(TAG, "Policy has bad format: " + rule);
- return null;
- }
-
- String intervalStr = str[0];
- String timesStr = str[1];
-
- if (intervalStr.isEmpty() || timesStr.isEmpty()) {
- Log.e(TAG, "One of the values is empty. Please check format: " + rule);
- return null;
- }
-
- char unit = intervalStr.charAt(intervalStr.length() - 1);
-
- // Removing last letter extension from string
- intervalStr = intervalStr.substring(0, intervalStr.length() - 1);
-
- int interval, times;
- try {
- interval = Integer.parseInt(intervalStr);
- times = Integer.parseInt(timesStr);
- } catch (NumberFormatException ex) {
- Log.d(TAG, "Invalid input Rule for interval " + rule);
- return null;
- }
-
- if (!TIME_UNITS_LOOKUP.containsKey(unit)) {
- Log.e(TAG, "Time units map does not contain extension " + unit);
- return null;
- }
-
- if (interval <= 0) {
- Log.e(TAG, "Wake up policy time must be > 0!" + interval);
- return null;
- }
-
- if (times <= 0) {
- Log.e(TAG, "Wake up attempts in policy must be > 0!" + times);
- return null;
- }
-
- interval *= TIME_UNITS_LOOKUP.get(unit);
-
- return new WakeupInterval(interval, times);
- }
-}
diff --git a/service/src/com/android/car/garagemode/GarageModeService.java b/service/src/com/android/car/garagemode/GarageModeService.java
index c9c34dd..4899938 100644
--- a/service/src/com/android/car/garagemode/GarageModeService.java
+++ b/service/src/com/android/car/garagemode/GarageModeService.java
@@ -16,335 +16,76 @@
package com.android.car.garagemode;
-import static android.car.settings.GarageModeSettingsObserver.GARAGE_MODE_ENABLED_URI;
-import static android.car.settings.GarageModeSettingsObserver.GARAGE_MODE_MAINTENANCE_WINDOW_URI;
-import static android.car.settings.GarageModeSettingsObserver.GARAGE_MODE_WAKE_UP_TIME_URI;
-
-import android.car.settings.CarSettings;
-import android.car.settings.GarageModeSettingsObserver;
import android.content.Context;
-import android.content.SharedPreferences;
-import android.net.Uri;
-import android.os.Handler;
-import android.os.IDeviceIdleController;
-import android.os.IMaintenanceActivityListener;
import android.os.Looper;
-import android.os.Message;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.preference.PreferenceManager;
-import android.provider.Settings;
-import android.util.Log;
-import com.android.car.CarPowerManagementService;
import com.android.car.CarServiceBase;
-import com.android.car.DeviceIdleControllerWrapper;
-import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import java.io.PrintWriter;
/**
- * Controls car garage mode.
- *
- * Car garage mode is a time window for the car to do maintenance work when the car is not in use.
- * The {@link com.android.car.garagemode.GarageModeService} interacts with
- * {@link com.android.car.CarPowerManagementService} to start and end garage mode.
- * A {@link com.android.car.garagemode.GarageModePolicy} defines when the garage mode should
- * start and how long it should last.
+ * Main service container for car Garage Mode.
+ * Garage Mode enables idle time in cars.
*/
-public class GarageModeService implements CarServiceBase,
- CarPowerManagementService.PowerEventProcessingHandler,
- CarPowerManagementService.PowerServiceEventListener,
- DeviceIdleControllerWrapper.DeviceMaintenanceActivityListener {
- private static final String TAG = "GarageModeService";
+public class GarageModeService implements CarServiceBase {
+ private static final Logger LOG = new Logger("Service");
- private static final int MSG_EXIT_GARAGE_MODE_EARLY = 0;
- private static final int MSG_WRITE_TO_PREF = 1;
+ private final Context mContext;
+ private final Controller mController;
- private static final String KEY_GARAGE_MODE_INDEX = "garage_mode_index";
-
- // wait for 10 seconds to allow maintenance activities to start (e.g., connecting to wifi).
- protected static final int MAINTENANCE_ACTIVITY_START_GRACE_PERIOD = 10 * 1000;
-
- private final CarPowerManagementService mPowerManagementService;
- protected final Context mContext;
-
- @VisibleForTesting
- @GuardedBy("this")
- protected boolean mInGarageMode;
- @VisibleForTesting
- @GuardedBy("this")
- protected boolean mMaintenanceActive;
- @VisibleForTesting
- @GuardedBy("this")
- protected int mGarageModeIndex;
-
- @GuardedBy("this")
- @VisibleForTesting
- protected int mMaintenanceWindow;
- @GuardedBy("this")
- private GarageModePolicy mPolicy;
- @GuardedBy("this")
- private boolean mGarageModeEnabled;
-
-
- private SharedPreferences mSharedPreferences;
- private final GarageModeSettingsObserver mContentObserver;
-
- private DeviceIdleControllerWrapper mDeviceIdleController;
- private final GarageModeHandler mHandler;
-
- private class GarageModeHandler extends Handler {
- GarageModeHandler(Looper looper) {
- super(looper);
- }
-
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case MSG_EXIT_GARAGE_MODE_EARLY:
- mPowerManagementService.notifyPowerEventProcessingCompletion(
- GarageModeService.this);
- break;
- case MSG_WRITE_TO_PREF:
- writeToPref(msg.arg1);
- break;
- }
- }
- }
-
- public GarageModeService(Context context, CarPowerManagementService powerManagementService) {
- this(context, powerManagementService, null, Looper.myLooper());
+ public GarageModeService(Context context) {
+ this(context, null);
}
@VisibleForTesting
- protected GarageModeService(Context context, CarPowerManagementService powerManagementService,
- DeviceIdleControllerWrapper deviceIdleController, Looper looper) {
+ protected GarageModeService(Context context, Controller controller) {
mContext = context;
- mPowerManagementService = powerManagementService;
- mHandler = new GarageModeHandler(looper);
- if (deviceIdleController == null) {
- mDeviceIdleController = new DefaultDeviceIdleController();
- } else {
- mDeviceIdleController = deviceIdleController;
- }
- mContentObserver = new GarageModeSettingsObserver(mContext, mHandler) {
- @Override
- public void onChange(boolean selfChange, Uri uri) {
- onSettingsChangedInternal(uri);
- }
- };
+ mController = (controller != null ? controller
+ : new Controller(context, Looper.myLooper()));
}
+ /**
+ * Initializes GarageMode
+ */
@Override
public void init() {
- init(
- GarageModePolicy.initFromResources(mContext),
- PreferenceManager.getDefaultSharedPreferences(
- mContext.createDeviceProtectedStorageContext()));
}
- @VisibleForTesting
- void init(GarageModePolicy policy, SharedPreferences prefs) {
- Log.d(TAG, "initializing GarageMode");
- mSharedPreferences = prefs;
- mPolicy = policy;
- final int index = mSharedPreferences.getInt(KEY_GARAGE_MODE_INDEX, 0);
- synchronized (this) {
- mMaintenanceActive = mDeviceIdleController.startTracking(this);
- mGarageModeIndex = index;
- readFromSettingsLocked(
- CarSettings.Global.KEY_GARAGE_MODE_MAINTENANCE_WINDOW,
- CarSettings.Global.KEY_GARAGE_MODE_ENABLED,
- CarSettings.Global.KEY_GARAGE_MODE_WAKE_UP_TIME);
- }
- mContentObserver.register();
- mPowerManagementService.registerPowerEventProcessingHandler(this);
- }
-
- public boolean isInGarageMode() {
- return mInGarageMode;
- }
-
+ /**
+ * Cleans up GarageMode processes
+ */
@Override
public void release() {
- Log.d(TAG, "releasing GarageModeService");
- mDeviceIdleController.stopTracking();
- mContentObserver.unregister();
}
+ /**
+ * Dumps useful information about GarageMode
+ * @param writer
+ */
@Override
public void dump(PrintWriter writer) {
- writer.println("mGarageModeIndex: " + mGarageModeIndex);
- writer.println("inGarageMode? " + mInGarageMode);
- writer.println("GarageModeEnabled " + mGarageModeEnabled);
- writer.println("GarageModeTimeWindow " + mMaintenanceWindow + " ms");
+ writer.println("GarageModeInProgress " + mController.isGarageModeActive());
}
- @Override
- public long onPrepareShutdown(boolean shuttingDown) {
- // this is the beginning of each garage mode.
- synchronized (this) {
- Log.d(TAG, "onPrepareShutdown is triggered. System is shutting down=" + shuttingDown);
- mInGarageMode = true;
- mGarageModeIndex++;
- mHandler.removeMessages(MSG_EXIT_GARAGE_MODE_EARLY);
- if (!mMaintenanceActive) {
- mHandler.sendMessageDelayed(
- mHandler.obtainMessage(MSG_EXIT_GARAGE_MODE_EARLY),
- MAINTENANCE_ACTIVITY_START_GRACE_PERIOD);
- }
- // We always reserve the maintenance window first. If later, we found no
- // maintenance work active, we will exit garage mode early after
- // MAINTENANCE_ACTIVITY_START_GRACE_PERIOD
- return mMaintenanceWindow;
- }
+ /**
+ * @return whether GarageMode is in progress. Used by {@link com.android.car.ICarImpl}.
+ */
+ public boolean isGarageModeActive() {
+ return mController.isGarageModeActive();
}
- @Override
- public void onPowerOn(boolean displayOn) {
- synchronized (this) {
- Log.d(TAG, "onPowerOn: " + displayOn);
- if (displayOn) {
- // the car is use now. reset the garage mode counter.
- mGarageModeIndex = 0;
- }
- }
+ /**
+ * Forces GarageMode to start. Used by {@link com.android.car.ICarImpl}.
+ */
+ public void forceStartGarageMode() {
+ mController.initiateGarageMode(null);
}
- @Override
- public int getWakeupTime() {
- synchronized (this) {
- if (!mGarageModeEnabled) {
- return 0;
- }
- return mPolicy.getNextWakeUpInterval(mGarageModeIndex);
- }
- }
-
- @Override
- public void onSleepExit() {
- // ignored
- }
-
- @Override
- public void onSleepEntry() {
- synchronized (this) {
- mInGarageMode = false;
- }
- }
-
- @Override
- public void onShutdown() {
- synchronized (this) {
- mHandler.sendMessage(
- mHandler.obtainMessage(MSG_WRITE_TO_PREF, mGarageModeIndex, 0));
- }
- }
-
- private void writeToPref(int index) {
- SharedPreferences.Editor editor = mSharedPreferences.edit();
- editor.putInt(KEY_GARAGE_MODE_INDEX, index);
- editor.commit();
- }
-
- @Override
- public void onMaintenanceActivityChanged(boolean active) {
- boolean shouldReportCompletion = false;
- synchronized (this) {
- Log.d(TAG, "onMaintenanceActivityChanged: " + active);
- mMaintenanceActive = active;
- if (!mInGarageMode) {
- return;
- }
-
- if (!active) {
- shouldReportCompletion = true;
- mInGarageMode = false;
- } else {
- // we are in garage mode, and maintenance work has just begun.
- mHandler.removeMessages(MSG_EXIT_GARAGE_MODE_EARLY);
- }
- }
- if (shouldReportCompletion) {
- // we are in garage mode, and maintenance work has finished.
- mPowerManagementService.notifyPowerEventProcessingCompletion(this);
- }
- }
-
-
- private static class DefaultDeviceIdleController extends DeviceIdleControllerWrapper {
- private IDeviceIdleController mDeviceIdleController;
- private MaintenanceActivityListener mMaintenanceActivityListener =
- new MaintenanceActivityListener();
-
- @Override
- public boolean startLocked() {
- mDeviceIdleController = IDeviceIdleController.Stub.asInterface(
- ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER));
- boolean active = false;
- try {
- active = mDeviceIdleController
- .registerMaintenanceActivityListener(mMaintenanceActivityListener);
- } catch (RemoteException e) {
- Log.e(TAG, "Unable to register listener with DeviceIdleController", e);
- }
- return active;
- }
-
- @Override
- public void stopTracking() {
- try {
- if (mDeviceIdleController != null) {
- mDeviceIdleController.unregisterMaintenanceActivityListener(
- mMaintenanceActivityListener);
- }
- } catch (RemoteException e) {
- Log.e(TAG, "Fail to unregister listener.", e);
- }
- }
-
- private final class MaintenanceActivityListener extends IMaintenanceActivityListener.Stub {
- @Override
- public void onMaintenanceActivityChanged(final boolean active) {
- DefaultDeviceIdleController.this.setMaintenanceActivity(active);
- }
- }
- }
-
- @GuardedBy("this")
- private void readFromSettingsLocked(String... keys) {
- for (String key : keys) {
- switch (key) {
- case CarSettings.Global.KEY_GARAGE_MODE_ENABLED:
- mGarageModeEnabled =
- Settings.Global.getInt(mContext.getContentResolver(), key, 1) == 1;
- break;
- case CarSettings.Global.KEY_GARAGE_MODE_MAINTENANCE_WINDOW:
- mMaintenanceWindow = Settings.Global.getInt(
- mContext.getContentResolver(), key,
- CarSettings.DEFAULT_GARAGE_MODE_MAINTENANCE_WINDOW);
- break;
- default:
- Log.e(TAG, "Unknown setting key " + key);
- }
- }
- }
-
- private void onSettingsChangedInternal(Uri uri) {
- synchronized (this) {
- Log.d(TAG, "Content Observer onChange: " + uri);
- if (uri.equals(GARAGE_MODE_ENABLED_URI)) {
- readFromSettingsLocked(CarSettings.Global.KEY_GARAGE_MODE_ENABLED);
- } else if (uri.equals(GARAGE_MODE_WAKE_UP_TIME_URI)) {
- readFromSettingsLocked(CarSettings.Global.KEY_GARAGE_MODE_WAKE_UP_TIME);
- } else if (uri.equals(GARAGE_MODE_MAINTENANCE_WINDOW_URI)) {
- readFromSettingsLocked(CarSettings.Global.KEY_GARAGE_MODE_MAINTENANCE_WINDOW);
- }
- Log.d(TAG, String.format(
- "onSettingsChanged %s. enabled: %s, windowSize: %d",
- uri, mGarageModeEnabled, mMaintenanceWindow));
- }
+ /**
+ * Stops and resets the GarageMode. Used by {@link com.android.car.ICarImpl}.
+ */
+ public void stopAndResetGarageMode() {
+ mController.resetGarageMode();
}
}
diff --git a/service/src/com/android/car/garagemode/Logger.java b/service/src/com/android/car/garagemode/Logger.java
new file mode 100644
index 0000000..220ee74
--- /dev/null
+++ b/service/src/com/android/car/garagemode/Logger.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2018 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.garagemode;
+
+import android.util.Log;
+
+class Logger {
+ private final String mTag;
+ private final String mPrefix;
+
+ Logger(String prefix) {
+ mTag = "GarageMode";
+ mPrefix = prefix;
+ }
+
+ /** Passing message further to Log.v() */
+ public void v(String msg) {
+ Log.v(mTag, buildMessage(msg));
+ }
+
+ /** Passing message further to Log.v() */
+ public void v(String msg, Exception ex) {
+ Log.v(mTag, buildMessage(msg), ex);
+ }
+
+ /** Passing message further to Log.i() */
+ public void i(String msg) {
+ Log.i(mTag, buildMessage(msg));
+ }
+
+ /** Passing message further to Log.i() */
+ public void i(String msg, Exception ex) {
+ Log.i(mTag, buildMessage(msg), ex);
+ }
+
+ /** Passing message further to Log.d() */
+ public void d(String msg) {
+ Log.d(mTag, buildMessage(msg));
+ }
+
+ /** Passing message further to Log.d() */
+ public void d(String msg, Exception ex) {
+ Log.d(mTag, buildMessage(msg), ex);
+ }
+
+ /** Passing message further to Log.w() */
+ public void w(String msg, Exception ex) {
+ Log.w(mTag, buildMessage(msg), ex);
+ }
+
+ /** Passing message further to Log.w() */
+ public void w(String msg) {
+ Log.w(mTag, buildMessage(msg));
+ }
+
+ /** Passing message further to Log.e() */
+ public void e(String msg) {
+ Log.e(mTag, buildMessage(msg));
+ }
+
+ /** Passing message further to Log.e() */
+ public void e(String msg, Exception ex) {
+ Log.e(mTag, buildMessage(msg), ex);
+ }
+
+ /** Passing message further to Log.e() */
+ public void e(String msg, Throwable ex) {
+ Log.e(mTag, buildMessage(msg), ex);
+ }
+
+ private String buildMessage(String msg) {
+ return String.format("[%s]: %s", mPrefix, msg);
+ }
+}
diff --git a/service/src/com/android/car/garagemode/WakeupInterval.java b/service/src/com/android/car/garagemode/WakeupInterval.java
deleted file mode 100644
index 659af9e..0000000
--- a/service/src/com/android/car/garagemode/WakeupInterval.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (C) 2015 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.garagemode;
-
-/**
- * Defines wake up interval which then will be used by
- * {@link com.android.car.garagemode.GarageModeService} to determine when to schedule next wake up
- * from {@link com.android.car.CarPowerManagementService}
- */
-class WakeupInterval {
- private int mWakeupInterval;
- private int mNumAttempts;
-
- WakeupInterval(int wakeupTime, int numAttempts) {
- mWakeupInterval = wakeupTime;
- mNumAttempts = numAttempts;
- }
-
- /**
- * Returns interval between now and next weke up.
- * @return interval in seconds
- */
- public int getWakeupInterval() {
- return mWakeupInterval;
- }
-
- /**
- * Returns amount of attempts to wake up with mWakeupInterval
- * @return amount of attempts
- */
- public int getNumAttempts() {
- return mNumAttempts;
- }
-}
diff --git a/service/src/com/android/car/garagemode/WakeupPolicy.java b/service/src/com/android/car/garagemode/WakeupPolicy.java
new file mode 100644
index 0000000..b049554
--- /dev/null
+++ b/service/src/com/android/car/garagemode/WakeupPolicy.java
@@ -0,0 +1,194 @@
+/*
+ * Copyright (C) 2018 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.garagemode;
+
+import android.content.Context;
+
+import com.android.car.R;
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.Map;
+
+/**
+ * Default garage mode policy.
+ *
+ * The first wake up time is set to be 1am the next day. And it keeps waking up every day for a
+ * week. After that, wake up every 7 days for a month, and wake up every 30 days thereafter.
+ */
+class WakeupPolicy {
+ private static final Logger LOG = new Logger("WakeupPolicy");
+ private static final Map<Character, Integer> TIME_UNITS_LOOKUP_SEC;
+ static {
+ TIME_UNITS_LOOKUP_SEC = new HashMap<>();
+ TIME_UNITS_LOOKUP_SEC.put('m', 60);
+ TIME_UNITS_LOOKUP_SEC.put('h', 3600);
+ TIME_UNITS_LOOKUP_SEC.put('d', 86400);
+ }
+ private LinkedList<WakeupInterval> mWakeupIntervals;
+ @VisibleForTesting protected int mIndex;
+
+ WakeupPolicy(String[] policy) {
+ mWakeupIntervals = parsePolicy(policy);
+ mIndex = 0;
+ }
+
+ /**
+ * Initializes Policy from config_garageModeCadence resource array.
+ * @param context to access resources
+ * @return Policy instance, created from values in resources
+ */
+ public static WakeupPolicy initFromResources(Context context) {
+ LOG.d("Initiating WakupPolicy from resources ...");
+ return new WakeupPolicy(
+ context.getResources().getStringArray(R.array.config_garageModeCadence));
+ }
+
+ /**
+ * Returns the interval in seconds, which defines next wake up time.
+ * @return the interval in seconds
+ */
+ public int getNextWakeUpInterval() {
+ if (mWakeupIntervals.size() == 0) {
+ LOG.e("No wake up policy configuration was loaded.");
+ return 0;
+ }
+
+ int index = mIndex;
+ for (WakeupInterval wakeupTime : mWakeupIntervals) {
+ if (index <= wakeupTime.getNumAttempts()) {
+ return wakeupTime.getWakeupInterval();
+ }
+ index -= wakeupTime.getNumAttempts();
+ }
+ LOG.w("No more garage mode wake ups scheduled; been sleeping too long.");
+ return 0;
+ }
+
+ protected int getWakupIntervalsAmount() {
+ return mWakeupIntervals.size();
+ }
+
+ private LinkedList<WakeupInterval> parsePolicy(String[] policy) {
+ LinkedList<WakeupInterval> intervals = new LinkedList<>();
+ if (policy == null || policy.length == 0) {
+ LOG.e("Trying to parse empty policies!");
+ return intervals;
+ }
+
+ for (String rule : policy) {
+ WakeupInterval interval = parseRule(rule);
+ if (interval == null) {
+ LOG.e("Invalid Policy! This rule has bad format: " + rule);
+ return new LinkedList<>();
+ }
+ intervals.add(interval);
+ }
+ return intervals;
+ }
+
+ private WakeupInterval parseRule(String rule) {
+ String[] str = rule.split(",");
+
+ if (str.length != 2) {
+ LOG.e("Policy has bad format: " + rule);
+ return null;
+ }
+
+ String intervalStr = str[0];
+ String timesStr = str[1];
+
+ if (intervalStr.isEmpty() || timesStr.isEmpty()) {
+ LOG.e("One of the values is empty. Please check format: " + rule);
+ return null;
+ }
+
+ char unit = intervalStr.charAt(intervalStr.length() - 1);
+
+ // Removing last letter extension from string
+ intervalStr = intervalStr.substring(0, intervalStr.length() - 1);
+
+ int interval, times;
+ try {
+ interval = Integer.parseInt(intervalStr);
+ times = Integer.parseInt(timesStr);
+ } catch (NumberFormatException ex) {
+ LOG.d("Invalid input Rule for interval " + rule);
+ return null;
+ }
+
+ if (!TIME_UNITS_LOOKUP_SEC.containsKey(unit)) {
+ LOG.e("Time units map does not contain extension " + unit);
+ return null;
+ }
+
+ if (interval <= 0) {
+ LOG.e("Wake up policy time must be > 0!" + interval);
+ return null;
+ }
+
+ if (times <= 0) {
+ LOG.e("Wake up attempts in policy must be > 0!" + times);
+ return null;
+ }
+
+ interval *= TIME_UNITS_LOOKUP_SEC.get(unit);
+
+ return new WakeupInterval(interval, times);
+ }
+
+ public void incrementCounter() {
+ mIndex++;
+ }
+
+ public void resetCounter() {
+ mIndex = 0;
+ }
+
+ /**
+ * Defines wake up interval which then will be used by
+ * {@link com.android.car.garagemode.GarageModeService} to schedule next wake up time in
+ * {@link android.car.hardware.power.CarPowerManager}
+ */
+ private class WakeupInterval {
+ private int mWakeupInterval;
+ private int mNumAttempts;
+
+ WakeupInterval(int wakeupTime, int numAttempts) {
+ mWakeupInterval = wakeupTime;
+ mNumAttempts = numAttempts;
+ }
+
+ /**
+ * Returns interval between now and next wakeup.
+ * @return interval in seconds
+ */
+ public int getWakeupInterval() {
+ return mWakeupInterval;
+ }
+
+ /**
+ * Returns amount of attempts to wake up with mWakeupInterval
+ * @return amount of attempts
+ */
+ public int getNumAttempts() {
+ return mNumAttempts;
+ }
+ }
+
+}
diff --git a/service/src/com/android/car/hal/PropertyHalServiceIds.java b/service/src/com/android/car/hal/PropertyHalServiceIds.java
index 6c5533d..e8d00ee 100644
--- a/service/src/com/android/car/hal/PropertyHalServiceIds.java
+++ b/service/src/com/android/car/hal/PropertyHalServiceIds.java
@@ -258,6 +258,9 @@
mProps.put(VehicleProperty.PERF_VEHICLE_SPEED, new Pair<>(
Car.PERMISSION_SPEED,
Car.PERMISSION_SPEED));
+ mProps.put(VehicleProperty.PERF_VEHICLE_SPEED_DISPLAY, new Pair<>(
+ Car.PERMISSION_SPEED,
+ Car.PERMISSION_SPEED));
mProps.put(VehicleProperty.ENGINE_COOLANT_TEMP, new Pair<>(
Car.PERMISSION_CAR_ENGINE_DETAILED,
Car.PERMISSION_CAR_ENGINE_DETAILED));
@@ -319,8 +322,8 @@
Car.PERMISSION_EXTERIOR_LIGHTS,
Car.PERMISSION_EXTERIOR_LIGHTS));
mProps.put(VehicleProperty.IGNITION_STATE, new Pair<>(
- Car.PERMISSION_CAR_POWER,
- Car.PERMISSION_CAR_POWER));
+ Car.PERMISSION_POWERTRAIN,
+ Car.PERMISSION_POWERTRAIN));
mProps.put(VehicleProperty.ABS_ACTIVE, new Pair<>(
Car.PERMISSION_CAR_DYNAMICS_STATE,
Car.PERMISSION_CAR_DYNAMICS_STATE));
diff --git a/service/src/com/android/car/hal/VmsHalService.java b/service/src/com/android/car/hal/VmsHalService.java
index fd84e2b..ef33b31 100644
--- a/service/src/com/android/car/hal/VmsHalService.java
+++ b/service/src/com/android/car/hal/VmsHalService.java
@@ -117,10 +117,26 @@
protected VmsHalService(VehicleHal vehicleHal) {
mVehicleHal = vehicleHal;
if (DBG) {
- Log.d(TAG, "started VmsHalService!");
+ Log.d(TAG, "Started VmsHalService!");
}
}
+ /**
+ * VMS subscribers should wait for a layers availability message which indicates
+ * the subscriber service is ready to handle subscription requests.
+ */
+ public void signalSubscriberServiceIsReady() {
+ notifyOfAvailabilityChange();
+ }
+
+ /**
+ * VMS publishers should wait for a subscription state message which indicates
+ * the publisher service is ready to handle offerings and publishing.
+ */
+ public void signalPublisherServiceIsReady() {
+ notifyOfSubscriptionChange();
+ }
+
public void addPublisherListener(VmsHalPublisherListener listener) {
mPublisherListeners.add(listener);
}
@@ -151,7 +167,7 @@
}
if (firstSubscriptionForLayer) {
notifyHalPublishers(layer, true);
- notifyClientPublishers();
+ notifyOfSubscriptionChange();
}
}
@@ -173,7 +189,7 @@
}
if (!layerHasSubscribers) {
notifyHalPublishers(layer, false);
- notifyClientPublishers();
+ notifyOfSubscriptionChange();
}
}
@@ -201,7 +217,7 @@
}
if (firstSubscriptionForLayer) {
notifyHalPublishers(layer, true);
- notifyClientPublishers();
+ notifyOfSubscriptionChange();
}
}
@@ -223,7 +239,7 @@
}
if (!layerHasSubscribers) {
notifyHalPublishers(layer, false);
- notifyClientPublishers();
+ notifyOfSubscriptionChange();
}
}
@@ -293,7 +309,7 @@
}
if (firstSubscriptionForLayer) {
notifyHalPublishers(layer, true);
- notifyClientPublishers();
+ notifyOfSubscriptionChange();
}
}
@@ -309,7 +325,7 @@
}
if (firstSubscriptionForLayer) {
notifyHalPublishers(layer, publisherId, true);
- notifyClientPublishers();
+ notifyOfSubscriptionChange();
}
}
@@ -329,7 +345,7 @@
}
if (!layerHasSubscribers) {
notifyHalPublishers(layer, false);
- notifyClientPublishers();
+ notifyOfSubscriptionChange();
}
}
@@ -350,7 +366,7 @@
}
if (!layerHasSubscribers) {
notifyHalPublishers(layer, publisherId, false);
- notifyClientPublishers();
+ notifyOfSubscriptionChange();
}
}
@@ -390,7 +406,11 @@
setSubscriptionToPublisherRequest(layer, publisherId, hasSubscribers);
}
- private void notifyClientPublishers() {
+ private void notifyOfSubscriptionChange() {
+ if (DBG) {
+ Log.d(TAG, "Notifying publishers on subscriptions");
+ }
+
// Notify the App publishers
for (VmsHalPublisherListener listener : mPublisherListeners) {
// Besides the list of layers, also a timestamp is provided to the clients.
@@ -405,7 +425,16 @@
*
* @param availableLayers the layers which publishers claim they made publish.
*/
- private void notifyOfAvailabilityChange(VmsAvailableLayers availableLayers) {
+ private void notifyOfAvailabilityChange() {
+ if (DBG) {
+ Log.d(TAG, "Notifying subscribers on layers availability");
+ }
+
+ VmsAvailableLayers availableLayers;
+ synchronized (mLock) {
+ availableLayers = mAvailableLayers.getAvailableLayers();
+ }
+
// notify the HAL
notifyAvailabilityChangeToHal(availableLayers);
@@ -417,18 +446,22 @@
@Override
public void init() {
- if (DBG) {
- Log.d(TAG, "init()");
- }
if (mIsSupported) {
mVehicleHal.subscribeProperty(this, HAL_PROPERTY_ID);
+ if (DBG) {
+ Log.d(TAG, "Initializing VmsHalService VHAL property");
+ }
+ } else {
+ if (DBG) {
+ Log.d(TAG, "VmsHalService VHAL property not supported");
+ }
}
}
@Override
public void release() {
if (DBG) {
- Log.d(TAG, "release()");
+ Log.d(TAG, "Releasing VmsHalService");
}
if (mIsSupported) {
mVehicleHal.unsubscribeProperty(this, HAL_PROPERTY_ID);
@@ -727,16 +760,13 @@
}
private void updateOffering(IBinder publisherToken, VmsLayersOffering offering) {
- VmsAvailableLayers availableLayers;
synchronized (mLock) {
mOfferings.put(publisherToken, offering);
// Update layers availability.
mAvailableLayers.setPublishersOffering(mOfferings.values());
-
- availableLayers = mAvailableLayers.getAvailableLayers();
}
- notifyOfAvailabilityChange(availableLayers);
+ notifyOfAvailabilityChange();
}
@Override
@@ -789,12 +819,15 @@
return setPropertyValue(vehiclePropertyValue);
}
- public boolean setPropertyValue(VehiclePropValue vehiclePropertyValue) {
- try {
- mVehicleHal.set(vehiclePropertyValue);
- return true;
- } catch (PropertyTimeoutException e) {
- Log.e(CarLog.TAG_PROPERTY, "set, property not ready 0x" + toHexString(HAL_PROPERTY_ID));
+ private boolean setPropertyValue(VehiclePropValue vehiclePropertyValue) {
+ if (mIsSupported) {
+ try {
+ mVehicleHal.set(vehiclePropertyValue);
+ return true;
+ } catch (PropertyTimeoutException e) {
+ Log.e(CarLog.TAG_PROPERTY,
+ "set, property not ready 0x" + toHexString(HAL_PROPERTY_ID));
+ }
}
return false;
}
diff --git a/service/src/com/android/car/user/CarUserService.java b/service/src/com/android/car/user/CarUserService.java
index 82e981f..1c9f839 100644
--- a/service/src/com/android/car/user/CarUserService.java
+++ b/service/src/com/android/car/user/CarUserService.java
@@ -22,14 +22,12 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
-import android.content.pm.UserInfo;
import android.location.LocationManager;
import android.os.UserHandle;
import android.os.UserManager;
import android.util.Log;
import com.android.car.CarServiceBase;
-import com.android.internal.annotations.VisibleForTesting;
import java.io.PrintWriter;
@@ -42,9 +40,6 @@
* <ol/>
*/
public class CarUserService extends BroadcastReceiver implements CarServiceBase {
- // Place holder for user name of the first user created.
- @VisibleForTesting
- static final String OWNER_NAME = "Driver";
private static final String TAG = "CarUserService";
private final Context mContext;
private final CarUserManagerHelper mCarUserManagerHelper;
@@ -94,13 +89,6 @@
if (mCarUserManagerHelper.getAllUsers().size() == 0) {
setSystemUserRestrictions();
mCarUserManagerHelper.initDefaultGuestRestrictions();
- // On very first boot, create an admin user and switch to that user.
- UserInfo admin = mCarUserManagerHelper.createNewAdminUser(OWNER_NAME);
- mCarUserManagerHelper.switchToUser(admin);
- mCarUserManagerHelper.setLastActiveUser(
- admin.id, /* skipGlobalSettings= */ false);
- } else {
- mCarUserManagerHelper.switchToUserId(mCarUserManagerHelper.getInitialUser());
}
} else if (Intent.ACTION_USER_SWITCHED.equals(intent.getAction())) {
// Update last active user if the switched-to user is a persistent, non-system user.
diff --git a/tests/CarDiagnosticVerifier/AndroidManifest.xml b/tests/CarDiagnosticVerifier/AndroidManifest.xml
deleted file mode 100644
index 6fa5d3c..0000000
--- a/tests/CarDiagnosticVerifier/AndroidManifest.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.google.android.car.diagnosticverifier">
-
- <uses-permission android:name="android.car.permission.CAR_DIAGNOSTICS" />
- <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
-
- <application android:label="Car Diagnostic Verification">
- <uses-library android:name="android.test.runner" />
-
- <activity android:name=".MainActivity">
- <intent-filter>
- <action android:name="android.intent.action.MAIN"/>
- <category android:name="android.intent.category.LAUNCHER"/>
- </intent-filter>
- </activity>
- </application>
-</manifest>
diff --git a/tests/CarDiagnosticVerifier/res/layout/result_message_item.xml b/tests/CarDiagnosticVerifier/res/layout/result_message_item.xml
deleted file mode 100644
index 5c742b6..0000000
--- a/tests/CarDiagnosticVerifier/res/layout/result_message_item.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="vertical"
- android:layout_width="match_parent"
- android:layout_height="wrap_content">
-
- <TextView
- android:id="@+id/result_message"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:padding="16dp"/>
-
-</LinearLayout>
\ No newline at end of file
diff --git a/tests/CarDiagnosticVerifier/res/layout/verifier_activity.xml b/tests/CarDiagnosticVerifier/res/layout/verifier_activity.xml
deleted file mode 100644
index 5aa2a6b..0000000
--- a/tests/CarDiagnosticVerifier/res/layout/verifier_activity.xml
+++ /dev/null
@@ -1,34 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:paddingLeft="16dp"
- android:paddingRight="16dp" >
-
- <TextView
- android:id="@+id/status_bar"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content" />
-
- <androidx.recyclerview.widget.RecyclerView
- android:id="@+id/verification_results"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:layout_below="@id/status_bar"
- android:layout_marginTop="16dp" />
-
-</RelativeLayout>
diff --git a/tests/CarDiagnosticVerifier/src/com/google/android/car/diagnosticverifier/DiagnosticJsonConverter.java b/tests/CarDiagnosticVerifier/src/com/google/android/car/diagnosticverifier/DiagnosticJsonConverter.java
deleted file mode 100644
index 85d4fc8..0000000
--- a/tests/CarDiagnosticVerifier/src/com/google/android/car/diagnosticverifier/DiagnosticJsonConverter.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * 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.diagnosticverifier;
-
-import android.car.diagnostic.CarDiagnosticEvent;
-import android.util.JsonReader;
-
-import com.android.car.vehiclehal.DiagnosticJson;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * This class provides method to convert JSON into car diagnostic event object.
- */
-public class DiagnosticJsonConverter {
-
- public static List<CarDiagnosticEvent> readFromJson(InputStream in) throws IOException {
- JsonReader reader = new JsonReader(new InputStreamReader(in, "UTF-8"));
-
- try {
- return readEventsArray(reader);
- } finally {
- reader.close();
- }
- }
-
- private static List<CarDiagnosticEvent> readEventsArray(JsonReader reader) throws IOException {
- List<CarDiagnosticEvent> events = new ArrayList<>();
-
- reader.beginArray();
- while (reader.hasNext()) {
- events.add(readEventAndCanonicalize(reader));
- }
- reader.endArray();
- return events;
- }
-
- public static CarDiagnosticEvent readEventAndCanonicalize(InputStream in) throws IOException {
- JsonReader reader = new JsonReader(new InputStreamReader(in, "UTF-8"));
- return readEventAndCanonicalize(reader);
- }
-
- /**
- * This method convert JSON to a car diagnostic event object.
- * Note: it will always set timestamp to 0 and set dtc to null if it is empty string.
- */
- private static CarDiagnosticEvent readEventAndCanonicalize(JsonReader reader)
- throws IOException {
- DiagnosticJson diagnosticJson = DiagnosticJson.build(reader);
- //Build event
- CarDiagnosticEvent.Builder builder = "freeze".equals(diagnosticJson.type) ?
- CarDiagnosticEvent.Builder.newFreezeFrameBuilder() :
- CarDiagnosticEvent.Builder.newLiveFrameBuilder();
- //Always skip timestamp because it is not useful for test
- builder.atTimestamp(0);
- for (int i = 0; i < diagnosticJson.intValues.size(); i++) {
- builder.withIntValue(diagnosticJson.intValues.keyAt(i),
- diagnosticJson.intValues.valueAt(i));
- }
- for (int i = 0; i < diagnosticJson.floatValues.size(); i++) {
- builder.withFloatValue(diagnosticJson.floatValues.keyAt(i),
- diagnosticJson.floatValues.valueAt(i));
- }
- //Always set dtc to null if it is empty string
- builder.withDtc("".equals(diagnosticJson.dtc) ? null : diagnosticJson.dtc);
-
- return builder.build();
- }
-}
diff --git a/tests/CarDiagnosticVerifier/src/com/google/android/car/diagnosticverifier/DiagnosticVerifier.java b/tests/CarDiagnosticVerifier/src/com/google/android/car/diagnosticverifier/DiagnosticVerifier.java
deleted file mode 100644
index 1b6e447..0000000
--- a/tests/CarDiagnosticVerifier/src/com/google/android/car/diagnosticverifier/DiagnosticVerifier.java
+++ /dev/null
@@ -1,244 +0,0 @@
-/*
- * 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.diagnosticverifier;
-
-import android.car.diagnostic.CarDiagnosticEvent;
-import android.util.JsonWriter;
-import android.util.Log;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.OutputStreamWriter;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * DiagVerifier implements verification logic for car diagnostic events.
- *
- * The main idea for the verification is similar to a "diff" command on two files, whereas here
- * is a diff on two event lists. The available diff operations are: "add", "delete", "modify"
- *
- * For example, think about doing a diff on two sequences:
- *
- * Truth: A B C D E
- * Received: A C D E F
- *
- * The goal is to find the minimal number of diff operations applied on Truth list in order to
- * become Received list. It is the same problem to find edit distance between two sequences and keep
- * track of the corresponding edit operations. This verifier applies dynamic programming algorithm
- * to find the minimal set of diff operations. And the result would be:
- *
- * Truth: A - C D E +
- * Received: A C D E F
- *
- * It means in order to become Received list, "B" will be missing and an extra "F" will be added
- * at the end of list.
- */
-public class DiagnosticVerifier {
-
- private static final String TAG = "DiagnosticVerifier";
- /**
- * Below are 4 diff operations when comparing two event lists
- */
- private static final int DELETE = 0;
- private static final int ADD = 1;
- private static final int MODIFY = 2;
- private static final int KEEP = 3;
-
- /**
- * A list of truth diagnostic events for comparison.
- */
- private final List<CarDiagnosticEvent> mTruthEventList = new ArrayList<>();
- /**
- * A list of received diagnostic events from car service.
- */
- private final List<CarDiagnosticEvent> mReceivedEventList = new ArrayList<>();
-
- /**
- * Definition of the verification result
- */
- static class VerificationResult {
- public final String testCase;
- public final boolean success;
- public final String errorMessage;
-
- private VerificationResult(String testCase, boolean success, String errorMessage) {
- this.testCase = testCase;
- this.success = success;
- this.errorMessage = errorMessage;
- }
-
- public static VerificationResult fromMessage(String testCase, String message) {
- return new VerificationResult(testCase, message.length() == 0, message);
- }
-
- public void writeToJson(JsonWriter jsonWriter) throws IOException {
- jsonWriter.beginObject();
-
- jsonWriter.name("testCase");
- jsonWriter.value(this.testCase);
-
- jsonWriter.name("success");
- jsonWriter.value(this.success);
-
- jsonWriter.name("errorMessage");
- jsonWriter.value(this.errorMessage);
-
- jsonWriter.endObject();
- }
- }
-
- public DiagnosticVerifier(List<CarDiagnosticEvent> truthEvents) {
- if (truthEvents != null) {
- for (CarDiagnosticEvent event : truthEvents) {
- CarDiagnosticEvent canonicalEvent = canonicalize(event);
- mTruthEventList.add(canonicalEvent);
- }
- }
- }
-
- public void receiveEvent(CarDiagnosticEvent event) {
- CarDiagnosticEvent newEvent = canonicalize(event);
- mReceivedEventList.add(newEvent);
- }
-
- public List<VerificationResult> verify() {
- List<Integer> diff = calculateDiffOperations();
- StringBuilder missingEventMsgBuilder = new StringBuilder();
- StringBuilder extraEventMsgBuilder = new StringBuilder();
- StringBuilder mismatchEventMsgBuilder = new StringBuilder();
- for (int i = 0, j = 0, k = diff.size() - 1; k >= 0; k--) {
- if (diff.get(k) == DELETE) {
- missingEventMsgBuilder.append(String.format(
- "Missing event at position %d: %s\n", i, mTruthEventList.get(i)));
- i++;
- } else if (diff.get(k) == ADD) {
- extraEventMsgBuilder.append(String.format(
- "Extra event at position %d: %s\n", i, mReceivedEventList.get(j)));
- j++;
- } else if (diff.get(k) == MODIFY) {
- mismatchEventMsgBuilder.append(String.format(
- "Mismatched event pair at position %d:\n" +
- "True event -- %s\nWrong event -- %s\n",
- i, mTruthEventList.get(i), mReceivedEventList.get(j)));
- i++;
- j++;
- } else {
- i++;
- j++;
- }
- }
- List<VerificationResult> results = new ArrayList<>();
- results.add(VerificationResult.fromMessage(
- "test_mismatched_event", mismatchEventMsgBuilder.toString()));
- results.add(VerificationResult.fromMessage(
- "test_missing_event", missingEventMsgBuilder.toString()));
- results.add(VerificationResult.fromMessage(
- "test_extra_event", extraEventMsgBuilder.toString()));
- return results;
- }
-
- /**
- * The function applies a dynamic programming algorithm to find the minimal set of diff
- * operations that applied on truth event list in order to become received event list
- */
- private List<Integer> calculateDiffOperations() {
- final int n = mTruthEventList.size();
- final int m = mReceivedEventList.size();
-
- int[][] diffTable = new int[n + 1][m + 1];
- int[][] costTable = new int[n + 1][m + 1];
-
- for (int i = 1; i <= n; i++) {
- costTable[i][0] = i;
- diffTable[i][0] = DELETE;
- }
-
- for (int i = 1; i <= m; i++) {
- costTable[0][i] = i;
- diffTable[0][i] = ADD;
- }
-
- for (int i = 1; i <= n; i++) {
- for (int j = 1; j <= m; j++) {
- int deleteCost = costTable[i - 1][j] + 1;
- int addCost = costTable[i][j - 1] + 1;
- int modifyCost = costTable[i - 1][j - 1];
-
- CarDiagnosticEvent trueEvent = mTruthEventList.get(i - 1);
- CarDiagnosticEvent receivedEvent = mReceivedEventList.get(j - 1);
-
- //TODO: Use a more meaningful comparison. Instead of strict object level equality,
- //can check logical equality and allow an acceptable difference.
- boolean isEqual = trueEvent.equals(receivedEvent);
- modifyCost += isEqual ? 0 : 1;
-
- int minCost = modifyCost;
- int move = isEqual ? KEEP : MODIFY;
- if (minCost > addCost) {
- minCost = addCost;
- move = ADD;
- }
- if (minCost > deleteCost) {
- minCost = deleteCost;
- move = DELETE;
- }
-
- costTable[i][j] = minCost;
- diffTable[i][j] = move;
- }
- }
- List<Integer> diff = new ArrayList<>();
-
- for (int i = n, j = m; i > 0 || j > 0; ) {
- diff.add(diffTable[i][j]);
- if (diffTable[i][j] == DELETE) {
- i--;
- } else if (diffTable[i][j] == ADD) {
- j--;
- } else {
- i--;
- j--;
- }
- }
- return diff;
- }
-
- /**
- * The function will canonicalize a given event by using JSON converter which will reset event
- * timestamp to 0 and set DTC field with empty string to null. Doing JSON conversion is because
- * CarDiagnosticEvent does not provide direct accessor for intValues and floatValues.
- */
- private CarDiagnosticEvent canonicalize(CarDiagnosticEvent event) {
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- JsonWriter writer = new JsonWriter(new OutputStreamWriter(out));
- CarDiagnosticEvent newEvent = event;
- try {
- event.writeToJson(writer);
- writer.flush();
- writer.close();
- byte[] rawJson = out.toByteArray();
- ByteArrayInputStream in = new ByteArrayInputStream(rawJson);
- newEvent = DiagnosticJsonConverter.readEventAndCanonicalize(in);
- in.close();
- out.close();
- } catch (IOException e) {
- Log.w(TAG, "Failed to clear timestamp ");
- }
- return newEvent;
- }
-}
diff --git a/tests/CarDiagnosticVerifier/src/com/google/android/car/diagnosticverifier/MainActivity.java b/tests/CarDiagnosticVerifier/src/com/google/android/car/diagnosticverifier/MainActivity.java
deleted file mode 100644
index 6814ad0..0000000
--- a/tests/CarDiagnosticVerifier/src/com/google/android/car/diagnosticverifier/MainActivity.java
+++ /dev/null
@@ -1,267 +0,0 @@
-/*
- * 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.diagnosticverifier;
-
-import android.app.Activity;
-import android.car.Car;
-import android.car.CarNotConnectedException;
-import android.car.diagnostic.CarDiagnosticEvent;
-import android.car.diagnostic.CarDiagnosticManager;
-import android.car.hardware.CarSensorManager;
-import android.content.BroadcastReceiver;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.ServiceConnection;
-import android.os.Bundle;
-import android.os.Environment;
-import android.os.IBinder;
-import android.util.JsonWriter;
-import android.util.Log;
-import android.widget.TextView;
-
-import androidx.recyclerview.widget.LinearLayoutManager;
-import androidx.recyclerview.widget.RecyclerView;
-
-import com.google.android.car.diagnosticverifier.DiagnosticVerifier.VerificationResult;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.OutputStreamWriter;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * The test app that does the verification of car diagnostic event data. It first reads the
- * truth (golden) event data from a JSON file upon starting. Then a broadcast intent such as:
- *
- * am broadcast -a com.google.android.car.diagnosticverifier.action.START_LISTEN
- *
- * will activate the car diagnostics listener. The test app will receive events from diagnostic API.
- * Once it receives all the events, a broadcast intent with "stop" action such as:
- *
- * am broadcast -a com.google.android.car.diagnosticverifier.action.STOP_LISTEN
- *
- * will deactivate the listener and start the verification process (see {@link DiagnosticVerifier}).
- *
- * Verification result will be output to a JSON file on device.
- */
-public class MainActivity extends Activity {
- public static final String TAG = "DiagnosticVerifier";
-
- public static final String ACTION_START_LISTEN =
- "com.google.android.car.diagnosticverifier.action.START_LISTEN";
- public static final String ACTION_STOP_LISTEN =
- "com.google.android.car.diagnosticverifier.action.STOP_LISTEN";
-
- private static final String DEFAULT_JSON_PATH = "/data/local/tmp/diag.json";
-
- private static final String JSON_PATH_KEY = "jsonPath";
- private static final String JSON_RESULT = "verification_result.json";
-
- private Car mCar;
- private CarDiagnosticManager mCarDiagnosticManager;
- private DiagnosticListener mDiagnosticListener;
- private BroadcastReceiver mBroadcastReceiver;
- private DiagnosticVerifier mVerifier;
- private TextView mStatusBar;
- private RecyclerView mRecyclerView;
- private VerificationResultAdapter mResultAdapter;
- private boolean mListening = false;
-
- private final ServiceConnection mCarConnectionListener =
- new ServiceConnection() {
- @Override
- public void onServiceConnected(ComponentName name, IBinder iBinder) {
- Log.d(TAG, "Connected to " + name.flattenToString());
- try {
- mCarDiagnosticManager =
- (CarDiagnosticManager) mCar.getCarManager(Car.DIAGNOSTIC_SERVICE);
- } catch (CarNotConnectedException e) {
- Log.e(TAG, "Failed to get a connection", e);
- }
- }
-
- @Override
- public void onServiceDisconnected(ComponentName name) {
- Log.d(TAG, "Disconnected from " + name.flattenToString());
-
- mCar = null;
- mCarDiagnosticManager = null;
- }
- };
-
- class DiagnosticListener implements CarDiagnosticManager.OnDiagnosticEventListener {
-
- @Override
- public void onDiagnosticEvent(CarDiagnosticEvent carDiagnosticEvent) {
- Log.v(TAG, "Received Car Diagnostic Event: " + carDiagnosticEvent.toString());
- mVerifier.receiveEvent(carDiagnosticEvent);
- }
- }
-
- class VerifierMsgReceiver extends BroadcastReceiver {
-
- @Override
- public void onReceive(Context context, Intent intent) {
- String action = intent.getAction();
- Log.d(TAG, "Received intent with action: " + action);
- if (ACTION_START_LISTEN.equals(action)) {
- try {
- startListen();
- } catch (CarNotConnectedException e) {
- Log.e(TAG, "Failed to listen for car diagnostic event", e);
- }
- } else if (ACTION_STOP_LISTEN.equals(action)) {
- stopListen();
- verify();
- }
- }
- }
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.verifier_activity);
-
- mStatusBar = (TextView) findViewById(R.id.status_bar);
-
- //Setting up RecyclerView to show verification result messages
- mRecyclerView = (RecyclerView) findViewById(R.id.verification_results);
- LinearLayoutManager layoutManager =
- new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
- mRecyclerView.setLayoutManager(layoutManager);
- mResultAdapter = new VerificationResultAdapter();
- mRecyclerView.setAdapter(mResultAdapter);
-
- //Connect to car service
- mCar = Car.createCar(this, mCarConnectionListener);
- mCar.connect();
-
- //Initialize broadcast intent receiver
- mBroadcastReceiver = new VerifierMsgReceiver();
- IntentFilter filter = new IntentFilter(ACTION_START_LISTEN);
- filter.addAction(ACTION_STOP_LISTEN);
- this.registerReceiver(mBroadcastReceiver, filter);
-
- //Read golden diagnostics JSON file
- String jsonPath = this.getIntent().getStringExtra(JSON_PATH_KEY);
- if (jsonPath == null || jsonPath.isEmpty()) {
- jsonPath = DEFAULT_JSON_PATH;
- }
- List<CarDiagnosticEvent> events;
- try {
- events = DiagnosticJsonConverter.readFromJson(new FileInputStream(jsonPath));
- } catch (IOException e) {
- throw new RuntimeException("Failed to read diagnostic JSON file", e);
- }
- Log.d(TAG, String.format("Read %d events from JSON file %s.", events.size(), jsonPath));
-
- mVerifier = new DiagnosticVerifier(events);
- }
-
- @Override
- protected void onDestroy() {
- if (mCar != null) {
- mCar.disconnect();
- }
- mVerifier = null;
- this.unregisterReceiver(mBroadcastReceiver);
- }
-
- private void startListen() throws CarNotConnectedException {
- if (mListening) {
- return;
- }
- if (mDiagnosticListener == null) {
- mDiagnosticListener = new DiagnosticListener();
- }
- Log.i(TAG, "Start listening for car diagnostics events");
- mCarDiagnosticManager.registerListener(
- mDiagnosticListener,
- CarDiagnosticManager.FRAME_TYPE_LIVE,
- CarSensorManager.SENSOR_RATE_NORMAL);
- mCarDiagnosticManager.registerListener(
- mDiagnosticListener,
- CarDiagnosticManager.FRAME_TYPE_FREEZE,
- CarSensorManager.SENSOR_RATE_NORMAL);
-
- mListening = true;
- mStatusBar.setText(R.string.status_receiving);
- }
-
- private void stopListen() {
- Log.i(TAG, "Stop listening for car diagnostics events");
- mCarDiagnosticManager.unregisterListener(mDiagnosticListener);
- mListening = false;
- }
-
- private boolean isExternalStorageWritable() {
- String state = Environment.getExternalStorageState();
- return Environment.MEDIA_MOUNTED.equals(state);
- }
-
- private File getResultJsonFile() throws IOException {
- if (!isExternalStorageWritable()) {
- throw new IOException("External storage is not writable. Cannot save content");
- }
-
- File resultJson = new File(Environment.getExternalStoragePublicDirectory(
- Environment.DIRECTORY_DOCUMENTS), JSON_RESULT);
- if (!resultJson.getParentFile().mkdirs()) {
- Log.w(TAG, "Parent directory may already exist");
- }
- return resultJson;
- }
-
- private void verify() {
- Log.d(TAG, "Start verifying car diagnostics events");
- mStatusBar.setText(R.string.status_verifying);
- List<VerificationResult> results = mVerifier.verify();
- mStatusBar.setText(R.string.status_done);
-
- if (results.isEmpty()) {
- Log.d(TAG, "Verification result is empty.");
- return;
- }
-
- List<String> resultMessages = new ArrayList<>();
- try {
- File resultJson = getResultJsonFile();
- JsonWriter writer = new JsonWriter(
- new OutputStreamWriter(new FileOutputStream(resultJson)));
-
- writer.beginArray();
- for (VerificationResult result : results) {
- resultMessages.add("Test case: " + result.testCase);
- resultMessages.add("Result: " + result.success);
- resultMessages.add(result.errorMessage);
- result.writeToJson(writer);
- }
- writer.endArray();
- writer.flush();
- writer.close();
- Log.i(TAG, "Verification result: " + resultJson.getAbsolutePath());
- } catch (IOException e) {
- Log.e(TAG, "Failed to save verification result.", e);
- }
- mResultAdapter.setResultMessages(resultMessages);
- }
-}
-
diff --git a/tests/CarDiagnosticVerifier/src/com/google/android/car/diagnosticverifier/VerificationResultAdapter.java b/tests/CarDiagnosticVerifier/src/com/google/android/car/diagnosticverifier/VerificationResultAdapter.java
deleted file mode 100644
index 36e584d..0000000
--- a/tests/CarDiagnosticVerifier/src/com/google/android/car/diagnosticverifier/VerificationResultAdapter.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * 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.diagnosticverifier;
-
-import android.content.Context;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.TextView;
-
-import androidx.recyclerview.widget.RecyclerView;
-
-import java.util.List;
-
-/**
- * A recycler view adapter for verification result messages
- */
-public class VerificationResultAdapter extends
- RecyclerView.Adapter<VerificationResultAdapter.VerificationResultViewHolder> {
-
- private List<String> mResultMessages;
-
- @Override
- public VerificationResultViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
- Context context = viewGroup.getContext();
- int messageItemLayoutId = R.layout.result_message_item;
- LayoutInflater inflater = LayoutInflater.from(context);
- boolean shouldAttachToParentImmediately = false;
-
- View view = inflater.inflate(
- messageItemLayoutId, viewGroup, shouldAttachToParentImmediately);
- return new VerificationResultViewHolder(view);
- }
-
- @Override
- public void onBindViewHolder(VerificationResultViewHolder verificationResultViewHolder, int i) {
- String resultMessage = mResultMessages.get(i);
- verificationResultViewHolder.mResultMessageTextView.setText(resultMessage);
- }
-
- @Override
- public int getItemCount() {
- if (mResultMessages == null) {
- return 0;
- }
- return mResultMessages.size();
- }
-
- public void setResultMessages(List<String> resultMessages) {
- mResultMessages = resultMessages;
- notifyDataSetChanged();
- }
-
- public class VerificationResultViewHolder extends RecyclerView.ViewHolder {
- public final TextView mResultMessageTextView;
-
- public VerificationResultViewHolder(View view) {
- super(view);
- mResultMessageTextView = (TextView) view.findViewById(R.id.result_message);
- }
- }
-}
diff --git a/tests/EmbeddedKitchenSinkApp/Android.mk b/tests/EmbeddedKitchenSinkApp/Android.mk
index 71adf6b..8239f3c 100644
--- a/tests/EmbeddedKitchenSinkApp/Android.mk
+++ b/tests/EmbeddedKitchenSinkApp/Android.mk
@@ -50,7 +50,7 @@
vehicle-hal-support-lib \
com.android.car.keventreader-client
-include packages/services/Car/car-support-lib/car-support.mk
+LOCAL_JAVA_LIBRARIES += android.car
include $(BUILD_PACKAGE)
diff --git a/tests/EmbeddedKitchenSinkApp/AndroidManifest.xml b/tests/EmbeddedKitchenSinkApp/AndroidManifest.xml
index 6e8e80f..c400bd8 100644
--- a/tests/EmbeddedKitchenSinkApp/AndroidManifest.xml
+++ b/tests/EmbeddedKitchenSinkApp/AndroidManifest.xml
@@ -65,10 +65,6 @@
android:name="android.car.application"
android:resource="@xml/automotive_app_desc" />
- <service android:name=".job.DishService"
- android:permission="android.permission.BIND_JOB_SERVICE">
- </service>
-
<activity android:name=".setting.CarServiceSettingsActivity"
android:label="@string/car_settings">
<intent-filter>
diff --git a/tests/EmbeddedKitchenSinkApp/res/layout/job_scheduler.xml b/tests/EmbeddedKitchenSinkApp/res/layout/job_scheduler.xml
deleted file mode 100644
index 3456263..0000000
--- a/tests/EmbeddedKitchenSinkApp/res/layout/job_scheduler.xml
+++ /dev/null
@@ -1,119 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2015 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.
--->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="horizontal"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
-
- <LinearLayout
- android:layout_width="0dp"
- android:layout_height="match_parent"
- android:layout_weight="1"
- android:orientation="vertical">
- <LinearLayout
- android:layout_width="wrap_content"
- android:layout_height="wrap_content">
- <Button
- android:id="@+id/refresh_button"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/refresh_button" />
- <Button
- android:id="@+id/cancel_button"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/cancel_button" />
- </LinearLayout>
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/job_info"
- android:textColor="@android:color/holo_red_dark" />
- <TextView
- android:id="@+id/current_jobs"
- android:layout_width="100dp"
- android:layout_height="wrap_content" />
- </LinearLayout>
-
- <LinearLayout
- android:layout_width="0dp"
- android:layout_height="match_parent"
- android:layout_weight="1"
- android:orientation="vertical">
- <Button
- android:id="@+id/schedule_button"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/schedule_button"/>
- <CheckBox
- android:id="@+id/require_idle"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/require_idle"/>
- <CheckBox
- android:id="@+id/require_charging"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/require_charging"/>
- <CheckBox
- android:id="@+id/require_persisted"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/require_persisted"/>
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/require_network"/>
- <RadioGroup
- android:id="@+id/network_group"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content">
-
- <RadioButton android:id="@+id/network_any"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/network_any"/>
-
- <RadioButton android:id="@+id/network_none"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/network_none"/>
-
- <RadioButton android:id="@+id/network_unmetered"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/network_unmetered"/>
- </RadioGroup>
-
- <LinearLayout
- android:layout_width="wrap_content"
- android:layout_height="wrap_content">
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/dish_num"/>
-
- <android.support.car.input.CarRestrictedEditText
- android:id="@+id/dish_num"
- android:layout_width="100dp"
- android:layout_height="40dp"
- android:inputType="number"
- android:text="@string/default_dish_num" />
- </LinearLayout>
-
- </LinearLayout>
-
-</LinearLayout>
\ No newline at end of file
diff --git a/tests/EmbeddedKitchenSinkApp/res/layout/sensors.xml b/tests/EmbeddedKitchenSinkApp/res/layout/sensors.xml
index 6ee854a..4d8c246 100644
--- a/tests/EmbeddedKitchenSinkApp/res/layout/sensors.xml
+++ b/tests/EmbeddedKitchenSinkApp/res/layout/sensors.xml
@@ -17,20 +17,46 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
- <!-- dummy one for top area -->
+ <!-- Top area -->
<LinearLayout
android:layout_width="match_parent"
- android:layout_height="50dp"
- android:orientation="vertical"
- android:layout_weight="1" />
+ android:layout_height="110dp"
+ android:orientation="vertical">
+ <TextView
+ android:id="@string/location_title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/location_title" />
+ <TextView
+ android:id="@+id/location_info"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+ <TextView
+ android:id="@+id/accel_info"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+ <TextView
+ android:id="@+id/gyro_info"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+ <TextView
+ android:id="@+id/mag_info"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+ </LinearLayout>
+ <!-- Bottom area -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:layout_weight="1" >
+ android:orientation="vertical">
<TextView
- android:id="@+id/sensor_info"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content" />
+ android:id="@+id/sensor_title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/sensor_title" />
+ <TextView
+ android:id="@+id/sensor_info"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
</LinearLayout>
</LinearLayout>
diff --git a/tests/EmbeddedKitchenSinkApp/res/layout/usb_host.xml b/tests/EmbeddedKitchenSinkApp/res/layout/usb_host.xml
index fbcc608..7a13c4f 100644
--- a/tests/EmbeddedKitchenSinkApp/res/layout/usb_host.xml
+++ b/tests/EmbeddedKitchenSinkApp/res/layout/usb_host.xml
@@ -28,7 +28,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView
- android:text="@+string/usb_resolving_handlers"
+ android:text="@string/usb_resolving_handlers"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical" />
diff --git a/tests/EmbeddedKitchenSinkApp/res/layout/vhal_listitem.xml b/tests/EmbeddedKitchenSinkApp/res/layout/vhal_listitem.xml
new file mode 100644
index 0000000..7057660
--- /dev/null
+++ b/tests/EmbeddedKitchenSinkApp/res/layout/vhal_listitem.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 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.
+-->
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="horizontal">
+ <TextView
+ android:id="@+id/textString"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="7"/>
+ <Button
+ android:id="@+id/infoButton"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="2"
+ android:text="config"/>
+ <Button
+ android:id="@+id/valueButton"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="3"
+ android:text="value"/>
+</LinearLayout>
diff --git a/tests/EmbeddedKitchenSinkApp/res/values/strings.xml b/tests/EmbeddedKitchenSinkApp/res/values/strings.xml
index 452fec8..c50d230 100644
--- a/tests/EmbeddedKitchenSinkApp/res/values/strings.xml
+++ b/tests/EmbeddedKitchenSinkApp/res/values/strings.xml
@@ -117,22 +117,6 @@
<string name="mock_audio_on">Audio Mocking On</string>
<string name="mock_audio_off">Audio Mocking Off</string>
- <!-- job scheduler -->
- <string name="schedule_button">Schedule a New Job</string>
- <string name="refresh_button">Refresh pending jobs</string>
- <string name="cancel_button">Cancel All Jobs</string>
- <string name="job_info">Current Pending Jobs</string>
- <string name="require_charging">Require Charging</string>
- <string name="require_persisted">Persisted</string>
- <string name="require_periodic">Periodic</string>
- <string name="require_network">Network Type</string>
- <string name="require_idle">Device Idle</string>
- <string name="dish_num">Number of Plates</string>
- <string name="default_dish_num">50</string>
- <string name="network_any">ANY</string>
- <string name="network_none">NONE</string>
- <string name="network_unmetered">UNMETERED</string>
-
<!-- keyboard test fragment -->
<string name="keyboard_test_title">Keyboard Test</string>
<string name="on_search">OnSearch:</string>
@@ -209,6 +193,8 @@
<string name="radio_na">N/A</string>
<!-- sensors test -->
+ <string name="location_title">Location/Orientation:</string>
+ <string name="sensor_title">Car Sensor Data:</string>
<string name="sensor_na">N/A</string>
<string name="sensor_environment">Environment[%1$s]: temperature=%2$s</string>
@@ -219,12 +205,6 @@
<string name="sensor_rpm">RPM[%1$s]: rpm=%2$s</string>
<string name="sensor_speed">Speed[%1$s]: speed=%2$s</string>
<string name="sensor_ignition_status">Ignition status[%1$s]: status=%2$s</string>
- <string name="sensor_compass">Compass[%1$s]: bear=%2$s, pitch=%3$s, roll=%4$s</string>
- <string name="sensor_accelerometer">Accelerometer[%1$s]: x=%2$s, y=%3$s, z=%4$s</string>
- <string name="sensor_gyroscope">Gyroscope[%1$s]: x=%2$s, y=%3$s, z=%4$s</string>
- <string name="sensor_location">Location[%1$s]: lat=%2$s, lon=%3$s, accuracy=%4$s, altitude=%5$s, speed=%6$s, bearing=%7$s</string>
- <string name="sensor_gps">GPS Satellites[%1$s]: inView: %2$s, inUse: %3$s. %4$s</string>
- <string name="sensor_single_gps_satellite">(%1$s): usedInFix: %2$s, prn: %3$s, snr: %4$s, azimuth: %5$s, elevation: %6$s</string>
<string name="sensor_wheel_ticks">Wheel Distance[%1$s]: reset=%2$s, FL=%3$s, FR=%4$s, RL=%5$s, RR=%6$s</string>
<string name="sensor_wheel_ticks_cfg">Wheel Distance Config: Wheels=%1$s, FL=%2$s, FR=%3$s, RL=%4$s, RR=%5$s</string>
<string name="sensor_abs_is_active">ABS[%1$s]: isActive=%2$s</string>
@@ -237,6 +217,7 @@
<string name="sensor_ev_charge_port_is_open">EV Charge Port Is Open[%1$s]: %2$s</string>
<string name="sensor_ev_charge_port_is_connected">EV Charge Port Is Connected[%1$s]: %2$s</string>
<string name="sensor_ev_charge_rate">EV Charge Rate[%1$s]: %2$s</string>
+ <string name="sensor_oil_level">Oil Level[%1$s]: %2$s</string>
<string name="volume_test">Volume Test</string>
<string name="volume_up_logical">Vol +</string>
diff --git a/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/CarEmulator.java b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/CarEmulator.java
index ecb734d..ca2d6b3 100644
--- a/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/CarEmulator.java
+++ b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/CarEmulator.java
@@ -17,6 +17,8 @@
package com.google.android.car.kitchensink;
+import com.google.android.collect.Lists;
+
import android.car.Car;
import android.content.Context;
import android.hardware.automotive.vehicle.V2_0.VehicleHwKeyInputAction;
@@ -24,6 +26,7 @@
import android.hardware.automotive.vehicle.V2_0.VehicleProperty;
import android.hardware.automotive.vehicle.V2_0.VehiclePropertyAccess;
import android.os.SystemClock;
+import android.util.SparseIntArray;
import com.android.car.ICarImpl;
import com.android.car.systeminterface.SystemInterface;
@@ -32,6 +35,10 @@
import com.android.car.vehiclehal.test.MockedVehicleHal.VehicleHalPropertyHandler;
import com.android.car.vehiclehal.test.VehiclePropConfigBuilder;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
public class CarEmulator {
private final Car mCar;
diff --git a/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/KitchenSinkActivity.java b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/KitchenSinkActivity.java
index 9453bf7..6f58d25 100644
--- a/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/KitchenSinkActivity.java
+++ b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/KitchenSinkActivity.java
@@ -16,20 +16,21 @@
package com.google.android.car.kitchensink;
-
+import android.car.Car;
+import android.car.CarAppFocusManager;
+import android.car.CarNotConnectedException;
import android.car.hardware.CarSensorManager;
import android.car.hardware.hvac.CarHvacManager;
import android.car.hardware.power.CarPowerManager;
import android.car.hardware.property.CarPropertyManager;
+import android.content.ComponentName;
import android.content.Intent;
+import android.content.ServiceConnection;
import android.content.pm.PackageManager;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
-import android.support.car.Car;
-import android.support.car.CarAppFocusManager;
-import android.support.car.CarConnectionCallback;
-import android.support.car.CarNotConnectedException;
+import android.os.IBinder;
import android.util.Log;
import androidx.car.drawer.CarDrawerActivity;
@@ -50,7 +51,6 @@
import com.google.android.car.kitchensink.displayinfo.DisplayInfoFragment;
import com.google.android.car.kitchensink.hvac.HvacTestFragment;
import com.google.android.car.kitchensink.input.InputTestFragment;
-import com.google.android.car.kitchensink.job.JobSchedulerFragment;
import com.google.android.car.kitchensink.notification.NotificationFragment;
import com.google.android.car.kitchensink.orientation.OrientationTestFragment;
import com.google.android.car.kitchensink.power.PowerTestFragment;
@@ -154,7 +154,6 @@
add("hvac", HvacTestFragment.class);
add("inst cluster", InstrumentClusterFragment.class);
add("input test", InputTestFragment.class);
- add("job scheduler", JobSchedulerFragment.class);
add("notification", NotificationFragment.class);
add("orientation test", OrientationTestFragment.class);
add("power test", PowerTestFragment.class);
@@ -227,7 +226,7 @@
mCarApi.disconnect();
mCarApi = null;
}
- mCarApi = Car.createCar(this, mCarConnectionCallback);
+ mCarApi = Car.createCar(this, mServiceConnection);
mCarApi.connect();
}
@@ -276,10 +275,9 @@
.commit();
}
- private final CarConnectionCallback mCarConnectionCallback =
- new CarConnectionCallback() {
+ private final ServiceConnection mServiceConnection = new ServiceConnection() {
@Override
- public void onConnected(Car car) {
+ public void onServiceConnected(ComponentName name, IBinder service) {
Log.d(TAG, "Connected to Car Service");
synchronized (mPropertyManagerReady) {
try {
@@ -301,7 +299,7 @@
}
@Override
- public void onDisconnected(Car car) {
+ public void onServiceDisconnected(ComponentName name) {
Log.d(TAG, "Disconnect from Car Service");
}
};
@@ -324,11 +322,11 @@
@Override
protected void populateViewHolder(DrawerItemViewHolder holder, int position) {
- holder.getTitle().setText(mMenuEntries.get(position).getText());
+ holder.getTitleView().setText(mMenuEntries.get(position).getText());
+ holder.itemView.setOnClickListener(v -> onItemClick(holder.getAdapterPosition()));
}
- @Override
- public void onItemClick(int position) {
+ private void onItemClick(int position) {
if ((position < 0) || (position >= mMenuEntries.size())) {
Log.wtf(TAG, "Unknown menu item: " + position);
return;
diff --git a/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/audio/AudioPlayer.java b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/audio/AudioPlayer.java
index 50a5e9e..74345aa 100644
--- a/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/audio/AudioPlayer.java
+++ b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/audio/AudioPlayer.java
@@ -23,6 +23,8 @@
import android.media.MediaPlayer;
import android.util.Log;
+import com.google.android.car.kitchensink.R;
+
import java.io.IOException;
import java.util.concurrent.atomic.AtomicBoolean;
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
index 964d812..d50f053 100644
--- a/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/cluster/FakeClusterNavigationActivity.java
+++ b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/cluster/FakeClusterNavigationActivity.java
@@ -17,13 +17,15 @@
package com.google.android.car.kitchensink.cluster;
import android.app.Activity;
+import android.car.Car;
+import android.car.CarNotConnectedException;
import android.car.cluster.CarInstrumentClusterManager;
import android.car.cluster.ClusterActivityState;
+import android.content.ComponentName;
+import android.content.ServiceConnection;
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.os.IBinder;
import android.util.Log;
import android.widget.ImageView;
import android.widget.RelativeLayout;
@@ -50,16 +52,15 @@
setContentView(R.layout.fake_cluster_navigation_activity);
mUnobscuredArea = findViewById(R.id.unobscuredArea);
- mCarApi = Car.createCar(this /* context */, new CarConnectionCallback() {
-
+ mCarApi = Car.createCar(this /* context */, new ServiceConnection() {
@Override
- public void onConnected(Car car) {
- onCarConnected(car);
+ public void onServiceConnected(ComponentName name, IBinder service) {
+ onCarConnected(mCarApi);
}
@Override
- public void onDisconnected(Car car) {
- onCarDisconnected(car);
+ public void onServiceDisconnected(ComponentName name) {
+ onCarDisconnected(mCarApi);
}
});
Log.i(TAG, "Connecting to car api...");
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 8e4483e..4f5fc5b 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,15 +16,17 @@
package com.google.android.car.kitchensink.cluster;
import android.app.AlertDialog;
+import android.car.Car;
+import android.car.CarAppFocusManager;
+import android.car.CarNotConnectedException;
import android.car.cluster.CarInstrumentClusterManager;
+import android.car.navigation.CarNavigationStatusManager;
+import android.content.ComponentName;
import android.content.Intent;
+import android.content.ServiceConnection;
import android.content.pm.PackageManager;
import android.os.Bundle;
-import android.support.car.Car;
-import android.support.car.CarAppFocusManager;
-import android.support.car.CarConnectionCallback;
-import android.support.car.CarNotConnectedException;
-import android.support.car.navigation.CarNavigationStatusManager;
+import android.os.IBinder;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
@@ -48,23 +50,25 @@
private CarAppFocusManager mCarAppFocusManager;
private Car mCarApi;
- private final CarConnectionCallback mCarConnectionCallback = new CarConnectionCallback() {
+ private final ServiceConnection mServiceConnection = new ServiceConnection() {
@Override
- public void onConnected(Car car) {
+ public void onServiceConnected(ComponentName name, IBinder service) {
Log.d(TAG, "Connected to Car Service");
try {
mCarNavigationStatusManager =
- mCarApi.getCarManager(CarNavigationStatusManager.class);
- mCarAppFocusManager = mCarApi.getCarManager(CarAppFocusManager.class);
+ (CarNavigationStatusManager) mCarApi.getCarManager(
+ Car.CAR_NAVIGATION_SERVICE);
+ mCarAppFocusManager =
+ (CarAppFocusManager) mCarApi.getCarManager(Car.APP_FOCUS_SERVICE);
} catch (CarNotConnectedException e) {
Log.e(TAG, "Car is not connected!", e);
}
}
@Override
- public void onDisconnected(Car car) {
- Log.d(TAG, "Disconnect from Car Service");
- }
+ public void onServiceDisconnected(ComponentName name) {
+ Log.d(TAG, "Disconnect from Car Service");
+ }
};
private void initCarApi() {
@@ -73,7 +77,7 @@
mCarApi = null;
}
- mCarApi = Car.createCar(getContext(), mCarConnectionCallback);
+ mCarApi = Car.createCar(getContext(), mServiceConnection);
mCarApi.connect();
}
@@ -138,8 +142,7 @@
mCarAppFocusManager
.addFocusListener(new CarAppFocusManager.OnAppFocusChangedListener() {
@Override
- public void onAppFocusChanged(CarAppFocusManager manager, int appType,
- boolean active) {
+ public void onAppFocusChanged(int appType, boolean active) {
Log.d(TAG, "onAppFocusChanged, appType: " + appType + " active: "
+ active);
}
@@ -151,7 +154,7 @@
CarAppFocusManager.OnAppFocusOwnershipCallback
focusCallback = new CarAppFocusManager.OnAppFocusOwnershipCallback() {
@Override
- public void onAppFocusOwnershipLost(CarAppFocusManager manager, int focus) {
+ public void onAppFocusOwnershipLost(int focus) {
Log.w(TAG, "onAppFocusOwnershipLost, focus: " + focus);
new AlertDialog.Builder(getContext())
.setTitle(getContext().getApplicationInfo().name)
@@ -160,7 +163,7 @@
}
@Override
- public void onAppFocusOwnershipGranted(CarAppFocusManager manager, int focus) {
+ public void onAppFocusOwnershipGranted(int focus) {
Log.w(TAG, "onAppFocusOwnershipGranted, focus: " + focus);
}
@@ -174,7 +177,7 @@
try {
boolean ownsFocus = mCarAppFocusManager.isOwningFocus(
- CarAppFocusManager.APP_FOCUS_TYPE_NAVIGATION, focusCallback);
+ focusCallback, CarAppFocusManager.APP_FOCUS_TYPE_NAVIGATION);
Log.d(TAG, "Owns APP_FOCUS_TYPE_NAVIGATION: " + ownsFocus);
if (!ownsFocus) {
throw new RuntimeException("Focus was not acquired.");
diff --git a/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/diagnostic/DiagnosticTestFragment.java b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/diagnostic/DiagnosticTestFragment.java
index 5569848..7f9b4e1 100644
--- a/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/diagnostic/DiagnosticTestFragment.java
+++ b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/diagnostic/DiagnosticTestFragment.java
@@ -18,12 +18,13 @@
import android.annotation.Nullable;
import android.car.Car;
+import android.car.CarNotConnectedException;
import android.car.diagnostic.CarDiagnosticEvent;
import android.car.diagnostic.CarDiagnosticManager;
import android.car.diagnostic.CarDiagnosticManager.OnDiagnosticEventListener;
+import android.car.hardware.CarSensorManager;
import android.graphics.Color;
import android.os.Bundle;
-import android.support.car.hardware.CarSensorManager;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
@@ -108,7 +109,7 @@
CarDiagnosticManager.FRAME_TYPE_FREEZE,
CarSensorManager.SENSOR_RATE_NORMAL);
}
- } catch (android.car.CarNotConnectedException|android.support.car.CarNotConnectedException e) {
+ } catch (CarNotConnectedException e) {
Log.e(TAG, "Car not connected or not supported", e);
}
}
diff --git a/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/input/InputTestFragment.java b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/input/InputTestFragment.java
index 34ea1cf..5128816 100644
--- a/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/input/InputTestFragment.java
+++ b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/input/InputTestFragment.java
@@ -30,6 +30,7 @@
import android.hardware.automotive.vehicle.V2_0.VehicleArea;
import android.hardware.automotive.vehicle.V2_0.VehicleDisplay;
import android.hardware.automotive.vehicle.V2_0.VehiclePropValue;
+import android.hardware.automotive.vehicle.V2_0.VehicleProperty;
import android.hardware.automotive.vehicle.V2_0.VehiclePropertyGroup;
import android.hardware.automotive.vehicle.V2_0.VehiclePropertyStatus;
import android.hardware.automotive.vehicle.V2_0.VehiclePropertyType;
diff --git a/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/job/JobSchedulerFragment.java b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/job/JobSchedulerFragment.java
deleted file mode 100644
index b82818f..0000000
--- a/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/job/JobSchedulerFragment.java
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- * Copyright (C) 2015 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.job;
-
-import android.app.job.JobInfo;
-import android.app.job.JobScheduler;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.SharedPreferences;
-import android.os.Bundle;
-import android.os.PersistableBundle;
-import android.util.Log;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.Button;
-import android.widget.CheckBox;
-import android.widget.EditText;
-import android.widget.RadioGroup;
-import android.widget.TextView;
-import android.widget.Toast;
-
-import androidx.annotation.Nullable;
-import androidx.fragment.app.Fragment;
-
-import com.google.android.car.kitchensink.R;
-
-import java.util.List;
-
-public class JobSchedulerFragment extends Fragment {
- private static final String TAG = "JobSchedulerFragment";
- private static final String PREFS_NEXT_JOB_ID = "next_job_id";
-
- private Button mScheduleButton;
- private Button mRefreshButton;
- private Button mCancelButton;
- private CheckBox mRequireCharging;
- private CheckBox mRequireIdle;
- private CheckBox mRequirePersisted;
- private RadioGroup mNetworkGroup;
- private EditText mDishNum;
- private TextView mJobInfo;
- private JobScheduler mJobScheduler;
-
- @Nullable
- @Override
- public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
- @Nullable Bundle savedInstanceState) {
- View v = inflater.inflate(R.layout.job_scheduler, container, false);
- mScheduleButton = (Button) v.findViewById(R.id.schedule_button);
- mScheduleButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- scheduleJob();
- }
- });
- mRefreshButton = (Button) v.findViewById(R.id.refresh_button);
- mRefreshButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- refreshCurrentJobs();
- }
- });
-
- mNetworkGroup = (RadioGroup) v.findViewById(R.id.network_group);
- mDishNum = (EditText) v.findViewById(R.id.dish_num);
- mRequireCharging = (CheckBox) v.findViewById(R.id.require_charging);
- mRequireIdle = (CheckBox) v.findViewById(R.id.require_idle);
- mRequirePersisted = (CheckBox) v.findViewById(R.id.require_persisted);
- mJobScheduler = (JobScheduler) getContext()
- .getSystemService(Context.JOB_SCHEDULER_SERVICE);
-
- mJobInfo = (TextView) v.findViewById(R.id.current_jobs);
-
- mCancelButton = (Button) v.findViewById(R.id.cancel_button);
- mCancelButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- mJobScheduler.cancelAll();
- refreshCurrentJobs();
- }
- });
- return v;
- }
-
- @Override
- public void onResume() {
- super.onResume();
- refreshCurrentJobs();
- }
-
- private void refreshCurrentJobs() {
- StringBuilder sb = new StringBuilder();
- List<JobInfo> jobs = mJobScheduler.getAllPendingJobs();
- for (JobInfo job : jobs) {
- sb.append("JobId: ");
- sb.append(job.getId());
- sb.append("\nDishCount: ");
- sb.append(job.getExtras().getInt(DishService.EXTRA_DISH_COUNT, 0));
- sb.append("\n");
- }
- mJobInfo.setText(sb.toString());
- }
-
- private void scheduleJob() {
- ComponentName jobComponentName = new ComponentName(getContext(), DishService.class);
- SharedPreferences prefs = getContext()
- .getSharedPreferences(PREFS_NEXT_JOB_ID, Context.MODE_PRIVATE);
- int jobId = prefs.getInt(PREFS_NEXT_JOB_ID, 0);
- PersistableBundle bundle = new PersistableBundle();
- int count = 50;
- try {
- count = Integer.valueOf(mDishNum.getText().toString());
- } catch (NumberFormatException e) {
- Log.e(TAG, "NOT A NUMBER!!!");
- }
-
- int selected = mNetworkGroup.getCheckedRadioButtonId();
- int networkType = JobInfo.NETWORK_TYPE_ANY;
- switch (selected) {
- case R.id.network_none:
- networkType = JobInfo.NETWORK_TYPE_NONE;
- break;
- case R.id.network_unmetered:
- networkType = JobInfo.NETWORK_TYPE_UNMETERED;
- break;
- case R.id.network_any:
- networkType = JobInfo.NETWORK_TYPE_ANY;
- break;
- }
- bundle.putInt(DishService.EXTRA_DISH_COUNT, count);
- JobInfo jobInfo = new JobInfo.Builder(jobId, jobComponentName)
- .setRequiresCharging(mRequireCharging.isChecked())
- .setRequiresDeviceIdle(mRequireIdle.isChecked())
- // TODO: figure out why we crash here even we hold
- // the RECEIVE_BOOT_COMPLETE permission
- //.setPersisted(mRequirePersisted.isChecked())
- .setExtras(bundle)
- .setRequiredNetworkType(networkType)
- .build();
-
-
- mJobScheduler.schedule(jobInfo);
- Toast.makeText(getContext(), "Scheduled: " + jobInfo, Toast.LENGTH_LONG ).show();
-
- Log.d(TAG, "Scheduled a job: " + jobInfo);
- SharedPreferences.Editor editor = prefs.edit();
- editor.putInt(PREFS_NEXT_JOB_ID, jobId + 1);
- editor.commit();
-
- refreshCurrentJobs();
- }
-}
diff --git a/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/power/PowerTestFragment.java b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/power/PowerTestFragment.java
index d24148d..f0183a0 100644
--- a/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/power/PowerTestFragment.java
+++ b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/power/PowerTestFragment.java
@@ -35,36 +35,26 @@
import com.google.android.car.kitchensink.KitchenSinkActivity;
import com.google.android.car.kitchensink.R;
-import java.util.concurrent.Executor;
-
public class PowerTestFragment extends Fragment {
private final boolean DBG = false;
private final String TAG = "PowerTestFragment";
private CarPowerManager mCarPowerManager;
private TextView mTvBootReason;
- private Executor mExecutor;
-
- private class ThreadPerTaskExecutor implements Executor {
- public void execute(Runnable r) {
- new Thread(r).start();
- }
- }
private final CarPowerManager.CarPowerStateListener mPowerListener =
- new CarPowerManager.CarPowerStateListener () {
- @Override
- public void onStateChanged(int state) {
- Log.i(TAG, "onStateChanged() state = " + state);
+ (state, future) -> {
+ if (future != null) {
+ future.complete(null);
}
+ Log.i(TAG, "onStateChanged() state = " + state);
};
@Override
public void onCreate(Bundle savedInstanceState) {
final Runnable r = () -> {
mCarPowerManager = ((KitchenSinkActivity) getActivity()).getPowerManager();
- mExecutor = new ThreadPerTaskExecutor();
try {
- mCarPowerManager.setListener(mPowerListener, mExecutor);
+ mCarPowerManager.setListener(mPowerListener);
} catch (CarNotConnectedException e) {
Log.e(TAG, "Car is not connected!");
} catch (IllegalStateException e) {
diff --git a/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/property/PropertyTestFragment.java b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/property/PropertyTestFragment.java
index 83bbfa9..d4b5a02 100644
--- a/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/property/PropertyTestFragment.java
+++ b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/property/PropertyTestFragment.java
@@ -76,9 +76,6 @@
@Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.property, container, false);
- mActivity = (KitchenSinkActivity) getHost();
- mMgr = mActivity.getPropertyManager();
-
// Get resource IDs
mAreaId = view.findViewById(R.id.sAreaId);
mEventLog = view.findViewById(R.id.tvEventLog);
diff --git a/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/sensor/LocationListeners.java b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/sensor/LocationListeners.java
new file mode 100644
index 0000000..b99f5da
--- /dev/null
+++ b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/sensor/LocationListeners.java
@@ -0,0 +1,166 @@
+/*
+ * Copyright (C) 2016 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.sensor;
+
+import android.content.Context;
+import android.hardware.Sensor;
+import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener;
+import android.hardware.SensorManager;
+import android.location.Location;
+import android.location.LocationListener;
+import android.location.LocationManager;
+import android.os.Bundle;
+import android.util.Log;
+
+
+public class LocationListeners {
+
+ private static final String TAG = "CAR.SENSOR.KS.location";
+
+ SensorsTestFragment.LocationInfoTextUpdateListener mTextUpdateHandler;
+
+ LocationManager mLocationMgr;
+ SensorManager mSensorMgr;
+
+
+ public LocationListeners(Context context,
+ SensorsTestFragment.LocationInfoTextUpdateListener listener) {
+ mTextUpdateHandler = listener;
+
+ mLocationMgr = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
+ mSensorMgr = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
+ }
+
+ public void startListening() {
+ if (mLocationMgr != null) {
+ if (mLocationMgr.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
+ mLocationMgr.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0,
+ mLocationListener);
+ mTextUpdateHandler.setMagField("waiting to hear from GPS");
+ } else {
+ mTextUpdateHandler.setLocationField("GPS_PROVIDER not available");
+ }
+ } else {
+ mTextUpdateHandler.setLocationField("LocationManager not available");
+ }
+
+ if (mSensorMgr != null) {
+ Sensor accelerometerSensor = mSensorMgr.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
+ Sensor magneticFieldSensor = mSensorMgr.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
+ Sensor gyroscopeSensor = mSensorMgr.getDefaultSensor(Sensor.TYPE_GYROSCOPE);
+
+ mSensorMgr.registerListener(mSensorListener, accelerometerSensor,
+ SensorManager.SENSOR_DELAY_FASTEST);
+ mSensorMgr.registerListener(mSensorListener, gyroscopeSensor,
+ SensorManager.SENSOR_DELAY_FASTEST);
+ mSensorMgr.registerListener(mSensorListener, magneticFieldSensor,
+ SensorManager.SENSOR_DELAY_FASTEST);
+
+ mTextUpdateHandler.setAccelField("waiting to hear from SensorManager");
+ mTextUpdateHandler.setGyroField("waiting to hear from SensorManager");
+ mTextUpdateHandler.setMagField("waiting to hear from SensorManager");
+ } else {
+ mTextUpdateHandler.setAccelField("SensorManager not available");
+ mTextUpdateHandler.setGyroField("SensorManager not available");
+ mTextUpdateHandler.setMagField("SensorManager not available");
+ }
+ }
+
+ public void stopListening() {
+ if (mLocationMgr != null) {
+ if (mLocationMgr.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
+ mLocationMgr.removeUpdates(mLocationListener);
+ mTextUpdateHandler.setMagField("GPS stopped");
+ }
+ }
+
+ if (mSensorMgr != null) {
+ mSensorMgr.unregisterListener(mSensorListener);
+ mTextUpdateHandler.setAccelField("SensorManager stopped");
+ mTextUpdateHandler.setGyroField("SensorManager stopped");
+ mTextUpdateHandler.setMagField("SensorManager stopped");
+ }
+ }
+
+
+ private final LocationListener mLocationListener = new LocationListener() {
+ @Override
+ public void onLocationChanged(Location location) {
+ String s = String.format("Location: lat=%10.6f, lon=%10.6f, altitude=%5.0f, "
+ + "speed=%5.1f, bearing=%3.0f, accuracy=%5.1f",
+ location.getLatitude(),
+ location.getLongitude(),
+ location.getAltitude(),
+ location.getSpeed(),
+ location.getBearing(),
+ location.getAccuracy());
+
+ mTextUpdateHandler.setLocationField(s);
+ }
+
+ @Override
+ public void onProviderEnabled(String provider) {
+ }
+
+ @Override
+ public void onProviderDisabled(String provider) {
+ }
+
+ @Override
+ public void onStatusChanged(String provider, int status, Bundle extras) {
+ }
+ };
+
+ private final SensorEventListener mSensorListener = new SensorEventListener() {
+ @Override
+ public void onSensorChanged(SensorEvent event) {
+ int type = event.sensor.getType();
+ switch (type) {
+ case Sensor.TYPE_GYROSCOPE:
+ String gs = String.format("Gyroscope Rad/s: (%6.2f, %6.2f, %6.2f)",
+ event.values[0], event.values[1], event.values[2]);
+ mTextUpdateHandler.setLocationField(gs);
+ break;
+ case Sensor.TYPE_MAGNETIC_FIELD:
+ // NOTE: If we wanted to report yaw/pitch/roll, we would use both
+ // accelerometer and magnetic data to compute R and I:
+ // SensorManager.getRotationMatrix(R, I,
+ // mLastAccelerometerData
+ // mLastMagneticFieldData);
+ // SensorManager.getOrientation(mR, orientation);
+ String ms = String.format("Magnetic uT: (%6.2f, %6.2f, %6.2f)",
+ event.values[0], event.values[1], event.values[2]);
+ mTextUpdateHandler.setLocationField(ms);
+ break;
+ case Sensor.TYPE_ACCELEROMETER:
+ String as = String.format("Accelerometer m/s2: (%6.2f, %6.2f, %6.2f)",
+ event.values[0], event.values[1], event.values[2]);
+ mTextUpdateHandler.setLocationField(as);
+ break;
+ default:
+ Log.w(TAG, "Unexpected sensor event type: " + type);
+ // Should never happen.
+ return;
+ }
+ }
+
+ @Override
+ public void onAccuracyChanged(Sensor sensor, int accuracy) {
+ }
+ };
+}
diff --git a/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/sensor/SensorsTestFragment.java b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/sensor/SensorsTestFragment.java
index 39392b9..77a6e1c 100644
--- a/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/sensor/SensorsTestFragment.java
+++ b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/sensor/SensorsTestFragment.java
@@ -75,7 +75,7 @@
synchronized (SensorsTestFragment.this) {
mEventMap.put(event.sensorType, event);
}
- refreshUi();
+ refreshSensorInfoText();
}
};
private final Handler mHandler = new Handler();
@@ -83,13 +83,19 @@
private final DateFormat mDateFormat = SimpleDateFormat.getDateTimeInstance();
private KitchenSinkActivity mActivity;
- private TextView mSensorInfo;
private Car mCar;
- private CarSensorManager mSensorManager;
+ private CarSensorManager mCarSensorManager;
+ private LocationListeners mLocationListener;
private String mNaString;
private int[] supportedSensors = new int[0];
private Set<String> mActivePermissions = new HashSet<String>();
+ private TextView mSensorInfo;
+ private TextView mLocationInfo;
+ private TextView mAccelInfo;
+ private TextView mGyroInfo;
+ private TextView mMagInfo;
+
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
@@ -100,7 +106,13 @@
View view = inflater.inflate(R.layout.sensors, container, false);
mActivity = (KitchenSinkActivity) getHost();
+
mSensorInfo = (TextView) view.findViewById(R.id.sensor_info);
+ mLocationInfo = (TextView) view.findViewById(R.id.location_info);
+ mAccelInfo = (TextView) view.findViewById(R.id.accel_info);
+ mGyroInfo = (TextView) view.findViewById(R.id.gyro_info);
+ mMagInfo = (TextView) view.findViewById(R.id.mag_info);
+
mNaString = getContext().getString(R.string.sensor_na);
return view;
}
@@ -118,24 +130,38 @@
@Override
public void onPause() {
super.onPause();
- if (mSensorManager != null) {
- mSensorManager.unregisterListener(mOnSensorChangedListener);
+ if (mCarSensorManager != null) {
+ mCarSensorManager.unregisterListener(mOnSensorChangedListener);
+ }
+ if (mLocationListener != null) {
+ mLocationListener.stopListening();
}
}
private void initSensors() {
try {
- mSensorManager =
- (CarSensorManager) ((KitchenSinkActivity) getActivity()).getSensorManager();
- supportedSensors = mSensorManager.getSupportedSensors();
+ if (mCarSensorManager == null) {
+ mCarSensorManager =
+ (CarSensorManager) ((KitchenSinkActivity) getActivity()).getSensorManager();
+ }
+ supportedSensors = mCarSensorManager.getSupportedSensors();
for (Integer sensor : supportedSensors) {
- mSensorManager.registerListener(mOnSensorChangedListener, sensor,
+ mCarSensorManager.registerListener(mOnSensorChangedListener, sensor,
CarSensorManager.SENSOR_RATE_NORMAL);
}
} catch (CarNotConnectedException e) {
Log.e(TAG, "Car not connected or not supported", e);
} catch (Exception e) {
- Log.e(TAG, "initSensors() exception caught: ", e);
+ Log.e(TAG, "initSensors() exception caught SensorManager: ", e);
+ }
+ try {
+ if (mLocationListener == null) {
+ mLocationListener = new LocationListeners(getContext(),
+ new LocationInfoTextUpdateListener());
+ }
+ mLocationListener.startListening();
+ } catch (Exception e) {
+ Log.e(TAG, "initSensors() exception caught from LocationListeners: ", e);
}
}
@@ -143,6 +169,7 @@
Set<String> missingPermissions = checkExistingPermissions();
if (!missingPermissions.isEmpty()) {
requestPermissions(missingPermissions);
+ // The callback with premission results will take care of calling initSensors for us
} else {
initSensors();
}
@@ -182,7 +209,7 @@
}
}
- private void refreshUi() {
+ private void refreshSensorInfoText() {
String summaryString;
synchronized (this) {
List<String> summary = new ArrayList<>();
@@ -257,7 +284,7 @@
}
// Get the config data
try {
- CarSensorConfig c = mSensorManager.getSensorConfig(
+ CarSensorConfig c = mCarSensorManager.getSensorConfig(
CarSensorManager.SENSOR_TYPE_WHEEL_TICK_DISTANCE);
summary.add(getContext().getString(R.string.sensor_wheel_ticks_cfg,
c.getInt(CarSensorConfig.WHEEL_TICK_DISTANCE_SUPPORTED_WHEELS),
@@ -294,6 +321,9 @@
case CarSensorManager.SENSOR_TYPE_EV_BATTERY_CHARGE_RATE:
summary.add(getEvChargeRate(event));
break;
+ case CarSensorManager.SENSOR_TYPE_ENGINE_OIL_LEVEL:
+ summary.add(getEngineOilLevel(event));
+ break;
default:
// Should never happen.
Log.w(TAG, "Unrecognized event type: " + toHexString(i));
@@ -316,6 +346,10 @@
return mDateFormat.format(new Date(event.timestamp / (1000L * 1000L)));
}
+ private String getTimestampNow() {
+ return mDateFormat.format(new Date(System.nanoTime() / (1000L * 1000L)));
+ }
+
private String getFuelLevel(CarSensorEvent event) {
String fuelLevel = mNaString;
if(event != null) {
@@ -370,4 +404,38 @@
return getContext().getString(R.string.sensor_ev_charge_rate, getTimestamp(event),
evChargeRate);
}
+
+ private String getEngineOilLevel(CarSensorEvent event) {
+ String engineOilLevel = mNaString;
+ if(event != null) {
+ engineOilLevel = String.valueOf(event.getCarEngineOilLevelData(null).engineOilLevel);
+ }
+ return getContext().getString(R.string.sensor_oil_level, getTimestamp(event),
+ engineOilLevel);
+ }
+
+ public class LocationInfoTextUpdateListener {
+ public void setLocationField(String value) {
+ setTimestampedTextField(mLocationInfo, value);
+ }
+
+ public void setAccelField(String value) {
+ setTimestampedTextField(mAccelInfo, value);
+ }
+
+ public void setGyroField(String value) {
+ setTimestampedTextField(mGyroInfo, value);
+ }
+
+ public void setMagField(String value) {
+ setTimestampedTextField(mMagInfo, value);
+ }
+
+ private void setTimestampedTextField(TextView text, String value) {
+ synchronized (SensorsTestFragment.this) {
+ text.setText(getTimestampNow() + ": " + value);
+ Log.d(TAG, "setText: " + value);
+ }
+ }
+ }
}
diff --git a/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/setting/CarServiceSettingsActivity.java b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/setting/CarServiceSettingsActivity.java
index 0ad1934..d5f2cf2 100644
--- a/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/setting/CarServiceSettingsActivity.java
+++ b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/setting/CarServiceSettingsActivity.java
@@ -18,7 +18,6 @@
import android.os.Bundle;
import android.preference.PreferenceActivity;
-import android.view.View;
import android.widget.Button;
import com.google.android.car.kitchensink.R;
@@ -33,12 +32,7 @@
super.onCreate(savedInstanceState);
Button button = new Button(this);
button.setText("Finish");
- button.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- finish();
- }
- });
+ button.setOnClickListener(view -> finish());
setListFooter(button);
}
@@ -49,8 +43,7 @@
@Override
protected boolean isValidFragment(String fragmentName) {
- if (GarageModeSettingsFragment.class.getName().equals(fragmentName)
- || UsbManagerFragment.class.getName().equals(fragmentName)) {
+ if (UsbManagerFragment.class.getName().equals(fragmentName)) {
return true;
}
return false;
diff --git a/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/setting/GarageModeSettingsFragment.java b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/setting/GarageModeSettingsFragment.java
deleted file mode 100644
index 4ace656..0000000
--- a/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/setting/GarageModeSettingsFragment.java
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * Copyright (C) 2016 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.setting;
-
-import static android.car.settings.CarSettings.Global.KEY_GARAGE_MODE_ENABLED;
-import static android.car.settings.CarSettings.Global.KEY_GARAGE_MODE_MAINTENANCE_WINDOW;
-import static android.car.settings.CarSettings.Global.KEY_GARAGE_MODE_WAKE_UP_TIME;
-import static android.car.settings.GarageModeSettingsObserver.GARAGE_MODE_ENABLED_URI;
-import static android.car.settings.GarageModeSettingsObserver.GARAGE_MODE_MAINTENANCE_WINDOW_URI;
-import static android.car.settings.GarageModeSettingsObserver.GARAGE_MODE_WAKE_UP_TIME_URI;
-
-import android.app.TimePickerDialog;
-import android.car.CarApiUtil;
-import android.car.settings.GarageModeSettingsObserver;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.Handler;
-import android.preference.Preference;
-import android.preference.PreferenceFragment;
-import android.preference.PreferenceScreen;
-import android.provider.Settings;
-import android.text.format.DateFormat;
-import android.util.Log;
-import android.widget.TimePicker;
-
-import com.google.android.car.kitchensink.R;
-
-import java.sql.Time;
-
-public class GarageModeSettingsFragment extends PreferenceFragment implements
- TimePickerDialog.OnTimeSetListener, Preference.OnPreferenceChangeListener {
-
- private static final String TAG = "GarageModeSettings";
- private Preference mTimePreference;
- private Preference mGarageSwitchPreference;
- private Preference mGarageLimitPreference;
-
- private int mGarageTimeHour;
- private int mGarageTimeMin;
-
- private GarageModeSettingsObserver mContentObserver;
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- addPreferencesFromResource(R.xml.garage_mode_prefs);
- mTimePreference = findPreference(KEY_GARAGE_MODE_WAKE_UP_TIME);
- mTimePreference.setOnPreferenceChangeListener(this);
- mGarageSwitchPreference = findPreference(KEY_GARAGE_MODE_ENABLED);
- mGarageSwitchPreference.setOnPreferenceChangeListener(this);
- mGarageLimitPreference = findPreference(KEY_GARAGE_MODE_MAINTENANCE_WINDOW);
- mGarageLimitPreference.setOnPreferenceChangeListener(this);
- refreshUI(KEY_GARAGE_MODE_ENABLED, KEY_GARAGE_MODE_WAKE_UP_TIME, KEY_GARAGE_MODE_MAINTENANCE_WINDOW);
- mContentObserver = new GarageModeSettingsObserver(getContext(), new Handler()) {
- @Override
- public void onChange(boolean selfChange, Uri uri) {
- onSettingsChangedInternal(uri);
- }
- };
- }
-
- @Override
- public void onResume() {
- super.onResume();
- mContentObserver.register();
- }
-
- @Override
- public void onPause() {
- super.onPause();
- mContentObserver.unregister();
- }
-
- private void refreshUI(String... keys) {
- for (String key : keys) {
- try {
- switch (key) {
- case KEY_GARAGE_MODE_ENABLED:
- mGarageSwitchPreference.setDefaultValue(
- Settings.Global.getInt(getContext().getContentResolver(), key)
- == 1);
- break;
- case KEY_GARAGE_MODE_WAKE_UP_TIME:
- int time[] = CarApiUtil.decodeGarageTimeSetting(
- Settings.Global.getString(getContext().getContentResolver(),
- KEY_GARAGE_MODE_WAKE_UP_TIME));
- mTimePreference.setSummary(
- DateFormat.getTimeFormat(getContext()).format(
- new Time(time[0], time[1], 0)));
- mGarageTimeHour = time[0];
- mGarageTimeMin = time[1];
- break;
- case KEY_GARAGE_MODE_MAINTENANCE_WINDOW:
- int limitMinutes = Settings.Global.getInt(getContext().getContentResolver(),
- key) / 60 / 1000;
- mGarageLimitPreference.setSummary(
- getString(R.string.garage_time_limit_summary, limitMinutes));
- break;
- }
- } catch (Settings.SettingNotFoundException e) {
- Log.e(TAG, "Settings not found " + key);
- }
- }
- }
-
- @Override
- public boolean onPreferenceTreeClick(PreferenceScreen screen, Preference preference) {
- if (preference == mTimePreference) {
- TimePickerDialogFragment dialog =
- TimePickerDialogFragment.newInstance(mGarageTimeHour, mGarageTimeMin);
- dialog.setTimeSetListener(this);
- dialog.show(getFragmentManager(), "time");
- return true;
- }
- return super.onPreferenceTreeClick(screen, preference);
- }
-
- @Override
- public boolean onPreferenceChange(Preference preference, Object newValue) {
- if (preference == mGarageSwitchPreference) {
- updateGarageSwitch((boolean) newValue);
- refreshUI(KEY_GARAGE_MODE_ENABLED);
- return true;
- } else if (preference == mGarageLimitPreference) {
- updateGarageTimeLimit(Integer.valueOf((String) newValue));
- refreshUI(KEY_GARAGE_MODE_MAINTENANCE_WINDOW);
- return true;
- }
-
- return false;
- }
-
- private void updateGarageSwitch(boolean newValue) {
- Settings.Global.putInt(getContext().getContentResolver(),
- KEY_GARAGE_MODE_ENABLED, newValue ? 1 : 0);
- }
-
- private void updateGarageTimeLimit(int newValue) {
- Settings.Global.putInt(getContext().getContentResolver(),
- KEY_GARAGE_MODE_MAINTENANCE_WINDOW, newValue * 60 * 1000);
- }
-
- private void updateGarageTime(String time) {
- Settings.Global.putString(getContext().getContentResolver(),
- KEY_GARAGE_MODE_WAKE_UP_TIME, time);
- }
-
- @Override
- public void onTimeSet(TimePicker timePicker, int hour, int minute) {
- updateGarageTime(CarApiUtil.encodeGarageTimeSetting(hour, minute));
- refreshUI(KEY_GARAGE_MODE_WAKE_UP_TIME);
- }
-
- private void onSettingsChangedInternal(Uri uri) {
- Log.d(TAG, "Content Observer onChange: " + uri);
- if (uri.equals(GARAGE_MODE_ENABLED_URI)) {
- refreshUI(KEY_GARAGE_MODE_ENABLED);
- } else if (uri.equals(GARAGE_MODE_WAKE_UP_TIME_URI)) {
- refreshUI(KEY_GARAGE_MODE_WAKE_UP_TIME);
- } else if (uri.equals(GARAGE_MODE_MAINTENANCE_WINDOW_URI)) {
- refreshUI(KEY_GARAGE_MODE_MAINTENANCE_WINDOW);
- }
- }
-}
\ No newline at end of file
diff --git a/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/storagelifetime/StorageLifetimeFragment.java b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/storagelifetime/StorageLifetimeFragment.java
index bf7af5d..7ab3a6a 100644
--- a/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/storagelifetime/StorageLifetimeFragment.java
+++ b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/storagelifetime/StorageLifetimeFragment.java
@@ -208,8 +208,7 @@
"\nBlock size: " + mStatFs.getBlockSizeLong() + " bytes" +
"\nfor a total free space of: " +
(mStatFs.getBlockSizeLong() * mStatFs.getAvailableBlocksLong() / MEGABYTE) + "MB");
- } catch (android.car.CarNotConnectedException|
- android.support.car.CarNotConnectedException e) {
+ } catch (CarNotConnectedException e) {
Log.e(TAG, "Car not connected or not supported", e);
}
}
diff --git a/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/vhal/VehicleHalFragment.java b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/vhal/VehicleHalFragment.java
index df5f0fc..c5998c9 100644
--- a/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/vhal/VehicleHalFragment.java
+++ b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/vhal/VehicleHalFragment.java
@@ -17,10 +17,11 @@
import android.annotation.Nullable;
import android.app.AlertDialog;
-import android.content.DialogInterface;
-import android.content.DialogInterface.OnClickListener;
+import android.content.Context;
import android.hardware.automotive.vehicle.V2_0.IVehicle;
+import android.hardware.automotive.vehicle.V2_0.StatusCode;
import android.hardware.automotive.vehicle.V2_0.VehiclePropConfig;
+import android.hardware.automotive.vehicle.V2_0.VehiclePropValue;
import android.hardware.automotive.vehicle.V2_0.VehicleProperty;
import android.os.Bundle;
import android.os.RemoteException;
@@ -28,11 +29,12 @@
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
-import android.widget.AdapterView;
-import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
+import android.widget.Button;
+import android.widget.LinearLayout;
import android.widget.ListView;
+import android.widget.TextView;
import androidx.fragment.app.Fragment;
import com.google.android.car.kitchensink.KitchenSinkActivity;
@@ -43,28 +45,12 @@
import java.util.stream.Collectors;
public class VehicleHalFragment extends Fragment {
+
private static final String TAG = "CAR.VEHICLEHAL.KS";
private KitchenSinkActivity mActivity;
private ListView mListView;
- private final OnClickListener mNopOnClickListener = new OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) { }
- };
-
- private final OnItemClickListener mOnClickListener = new OnItemClickListener() {
- @Override
- public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
- HalPropertyInfo entry = (HalPropertyInfo)parent.getItemAtPosition(position);
- AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
- builder.setTitle("Info for " + entry.name)
- .setPositiveButton(android.R.string.yes, mNopOnClickListener)
- .setMessage(entry.config.toString())
- .show();
- }
- };
-
@Nullable
@Override
public View onCreateView(LayoutInflater inflater,
@@ -73,8 +59,6 @@
View view = inflater.inflate(R.layout.vhal, container, false);
mActivity = (KitchenSinkActivity) getHost();
mListView = view.findViewById(R.id.hal_prop_list);
- mListView.setOnItemClickListener(mOnClickListener);
-
return view;
}
@@ -103,12 +87,11 @@
.sorted()
.collect(Collectors.toList());
- mListView.setAdapter(new ArrayAdapter<HalPropertyInfo>(mActivity,
- android.R.layout.simple_list_item_1,
- supportedProperties));
+ mListView.setAdapter(new ListAdapter(mActivity, vehicle, supportedProperties));
}
private static class HalPropertyInfo implements Comparable<HalPropertyInfo> {
+
public final int id;
public final String name;
public final VehiclePropConfig config;
@@ -126,10 +109,7 @@
@Override
public boolean equals(Object other) {
- if (other instanceof HalPropertyInfo) {
- return ((HalPropertyInfo)other).id == id;
- }
- return false;
+ return other instanceof HalPropertyInfo && ((HalPropertyInfo) other).id == id;
}
@Override
@@ -141,5 +121,79 @@
public int compareTo(HalPropertyInfo halPropertyInfo) {
return name.compareTo(halPropertyInfo.name);
}
+
+ public String getValue(IVehicle vehicle) {
+ String result[] = new String[] {"<unknown>"};
+
+ try {
+ VehiclePropValue request = new VehiclePropValue();
+ // TODO: add zones support
+ request.prop = id;
+
+ // NB: this call is synchronous
+ vehicle.get(request, (status, propValue) -> {
+ if (status == StatusCode.OK) {
+ result[0] = propValue.value.toString();
+ }
+ });
+ } catch (android.os.RemoteException e) {
+ Log.e(TAG, "unable to read property " + name, e);
+ }
+
+ return result[0];
+ }
+ }
+
+ private static final class ListAdapter extends ArrayAdapter<HalPropertyInfo> {
+ private static final int RESOURCE_ID = R.layout.vhal_listitem;
+
+ // cannot use superclass' LayoutInflater as it is private
+ private final LayoutInflater mLayoutInflater;
+ private final IVehicle mVehicle;
+
+ ListAdapter(Context context, IVehicle vehicle, List<HalPropertyInfo> properties) {
+ super(context, RESOURCE_ID, properties);
+ mVehicle = vehicle;
+ mLayoutInflater = LayoutInflater.from(context);
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ final HalPropertyInfo item = getItem(position);
+
+ final LinearLayout viewLayout;
+ if (convertView != null && convertView instanceof LinearLayout) {
+ viewLayout = (LinearLayout)convertView;
+ } else {
+ // this is the value used by the superclass's view inflater
+ final boolean attachToRoot = false;
+
+ viewLayout =
+ (LinearLayout)mLayoutInflater.inflate(RESOURCE_ID, parent, attachToRoot);
+ }
+
+ TextView textString = viewLayout.findViewById(R.id.textString);
+ Button infoButton = viewLayout.findViewById(R.id.infoButton);
+ Button valueButton = viewLayout.findViewById(R.id.valueButton);
+
+ infoButton.setOnClickListener(btn -> {
+ AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
+ builder.setTitle("Configuration for " + item.name)
+ .setPositiveButton(android.R.string.yes, (x, y) -> { })
+ .setMessage(item.config.toString())
+ .show();
+ });
+
+ valueButton.setOnClickListener(btn -> {
+ AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
+ builder.setTitle("Value for " + item.name)
+ .setPositiveButton(android.R.string.yes, (x, y) -> { })
+ .setMessage(item.getValue(mVehicle))
+ .show();
+ });
+
+ textString.setText(item.toString());
+ return viewLayout;
+ }
}
}
diff --git a/tests/CarDiagnosticVerifier/Android.mk b/tests/GarageModeTestApp/Android.mk
similarity index 84%
rename from tests/CarDiagnosticVerifier/Android.mk
rename to tests/GarageModeTestApp/Android.mk
index e66c7a1..a3e60f8 100644
--- a/tests/CarDiagnosticVerifier/Android.mk
+++ b/tests/GarageModeTestApp/Android.mk
@@ -1,4 +1,4 @@
-# Copyright (C) 2017 The Android Open Source Project
+# Copyright (C) 2018 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.
@@ -15,18 +15,18 @@
#
LOCAL_PATH := $(call my-dir)
+
include $(CLEAR_VARS)
-LOCAL_MODULE_TAGS := optional
-
-# Only compile source java files in this apk.
LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
-LOCAL_PACKAGE_NAME := CarDiagnosticVerifier
+LOCAL_PACKAGE_NAME := GarageModeTestApp
LOCAL_PRIVATE_PLATFORM_APIS := true
+LOCAL_MODULE_TAGS := optional
+
LOCAL_JAVA_VERSION := 1.8
LOCAL_PROGUARD_ENABLED := disabled
@@ -37,11 +37,14 @@
LOCAL_PRIVILEGED_MODULE := true
+LOCAL_CERTIFICATE := platform
+
LOCAL_STATIC_JAVA_LIBRARIES += vehicle-hal-support-lib
-LOCAL_STATIC_ANDROID_LIBRARIES := \
+LOCAL_STATIC_ANDROID_LIBRARIES += \
+ androidx.car_car \
androidx.legacy_legacy-support-v4 \
- androidx.recyclerview_recyclerview
+ androidx.appcompat_appcompat
LOCAL_JAVA_LIBRARIES += android.car
diff --git a/tests/GarageModeTestApp/AndroidManifest.xml b/tests/GarageModeTestApp/AndroidManifest.xml
new file mode 100644
index 0000000..b33520f
--- /dev/null
+++ b/tests/GarageModeTestApp/AndroidManifest.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.google.android.car.garagemode.testapp"
+ android:sharedUserId="android.uid.system">
+
+ <uses-sdk
+ android:minSdkVersion="24"
+ android:targetSdkVersion='25'/>
+ <uses-permission android:name="android.car.permission.CAR_DRIVING_STATE" />
+ <uses-permission android:name="android.permission.BIND_JOB_SERVICE" />
+
+ <application android:label="GarageModeTestApp">
+ <activity android:name=".MainActivity"
+ android:theme="@style/GarageModeTheme"
+ android:label="@string/app_name">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="android.intent.category.LAUNCHER"/>
+ </intent-filter>
+ <meta-data android:name="distractionOptimized" android:value="true"/>
+ </activity>
+ <service android:name=".DishService"
+ android:permission="android.permission.BIND_JOB_SERVICE">
+ </service>
+ </application>
+</manifest>
diff --git a/car_product/overlay/frameworks/base/packages/SystemUI/res/drawable/volume_dialog_background.xml b/tests/GarageModeTestApp/res/drawable/border.xml
similarity index 65%
rename from car_product/overlay/frameworks/base/packages/SystemUI/res/drawable/volume_dialog_background.xml
rename to tests/GarageModeTestApp/res/drawable/border.xml
index 345692f..de84a3c 100644
--- a/car_product/overlay/frameworks/base/packages/SystemUI/res/drawable/volume_dialog_background.xml
+++ b/tests/GarageModeTestApp/res/drawable/border.xml
@@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2017 The Android Open Source Project
+<!-- Copyright (C) 2018 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.
@@ -14,13 +13,14 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<shape xmlns:android="http://schemas.android.com/apk/res/android" >
- <solid android:color="?android:attr/colorBackgroundFloating" />
- <padding
- android:bottom="5dp"
- android:left="5dp"
- android:right="5dp"
- android:top="5dp" />
- <corners android:bottomLeftRadius="20dp"
- android:bottomRightRadius="20dp"/>
-</shape>
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="rectangle">
+ <corners
+ android:bottomRightRadius="5dp"
+ android:bottomLeftRadius="5dp"
+ android:topLeftRadius="5dp"
+ android:topRightRadius="5dp"/>
+ <stroke
+ android:width="2dip"
+ android:color="#212121" />
+</shape>
\ No newline at end of file
diff --git a/tests/CarDiagnosticVerifier/res/values/strings.xml b/tests/GarageModeTestApp/res/layout/activity_content.xml
similarity index 63%
copy from tests/CarDiagnosticVerifier/res/values/strings.xml
copy to tests/GarageModeTestApp/res/layout/activity_content.xml
index ca6b33a..4ae4c8d 100644
--- a/tests/CarDiagnosticVerifier/res/values/strings.xml
+++ b/tests/GarageModeTestApp/res/layout/activity_content.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2017 The Android Open Source Project
+<!-- Copyright (C) 2018 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.
@@ -13,8 +13,9 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<resources>
- <string name="status_receiving">Receiving car diagnostic events...</string>
- <string name="status_verifying">Verifying car diagnostic events...</string>
- <string name="status_done">Done with verification</string>
-</resources>
+<!-- We use this container to place app fragments. It insets the fragment contents -->
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/activity_content"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+</FrameLayout>
\ No newline at end of file
diff --git a/tests/GarageModeTestApp/res/layout/job_info_row.xml b/tests/GarageModeTestApp/res/layout/job_info_row.xml
new file mode 100644
index 0000000..92c633b
--- /dev/null
+++ b/tests/GarageModeTestApp/res/layout/job_info_row.xml
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 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.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+ <TextView
+ android:id="@+id/jobId"
+ android:layout_height="match_parent"
+ android:layout_width="wrap_content"
+ android:layout_margin="5dp"
+ android:gravity="center_vertical"/>
+ <LinearLayout
+ android:layout_height="match_parent"
+ android:layout_width="wrap_content"
+ android:orientation="vertical">
+ <TextView
+ style="@style/ListEntryField"
+ android:id="@+id/requiredNetwork"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"/>
+ <TextView
+ style="@style/ListEntryField"
+ android:id="@+id/isPeriodic"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"/>
+ </LinearLayout>
+ <LinearLayout
+ android:layout_height="match_parent"
+ android:layout_width="wrap_content"
+ android:orientation="vertical">
+ <TextView
+ style="@style/ListEntryField"
+ android:id="@+id/isPersisted"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"/>
+ <TextView
+ style="@style/ListEntryField"
+ android:id="@+id/isPrefetch"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"/>
+ </LinearLayout>
+ <LinearLayout
+ android:layout_height="match_parent"
+ android:layout_width="wrap_content"
+ android:orientation="vertical">
+ <TextView
+ style="@style/ListEntryField"
+ android:id="@+id/isRequireBatteryNotLow"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"/>
+ <TextView
+ style="@style/ListEntryField"
+ android:id="@+id/isRequireCharging"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"/>
+ </LinearLayout>
+ <LinearLayout
+ android:layout_height="match_parent"
+ android:layout_width="wrap_content"
+ android:orientation="vertical">
+ <TextView
+ style="@style/ListEntryField"
+ android:id="@+id/isRequireDeviceIdle"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"/>
+ <TextView
+ style="@style/ListEntryField"
+ android:id="@+id/isRequireStorageNotLow"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"/>
+ </LinearLayout>
+</LinearLayout>
diff --git a/tests/GarageModeTestApp/res/layout/offcar_testing.xml b/tests/GarageModeTestApp/res/layout/offcar_testing.xml
new file mode 100644
index 0000000..c14aa07
--- /dev/null
+++ b/tests/GarageModeTestApp/res/layout/offcar_testing.xml
@@ -0,0 +1,179 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 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.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:weightSum="2">
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_weight="1"
+ android:orientation="vertical">
+ <LinearLayout
+ style="@style/SectionContainer"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+ <TextView
+ style="@style/SectionHeader"
+ android:text="@string/section_header_garage_mode_config"/>
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:weightSum="2">
+ <Button
+ style="@style/Button"
+ android:id="@+id/enterGarageModeBtn"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_weight="1"
+ android:text="@string/button_enter_garage_mode"/>
+ <Button
+ style="@style/Button"
+ android:id="@+id/exitGarageModeBtn"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_weight="1"
+ android:text="@string/button_exit_garage_mode"/>
+ </LinearLayout>
+ </LinearLayout>
+ <LinearLayout
+ style="@style/SectionContainer"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+ <TextView
+ style="@style/SectionHeader"
+ android:text="@string/section_header_watchdog"/>
+ <ScrollView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:fillViewport="true">
+ <TextView
+ android:id="@+id/garageModeWatchdog"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:textSize="18sp"
+ android:text="@string/no_results"/>
+ </ScrollView>
+ </LinearLayout>
+ </LinearLayout>
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_weight="1"
+ android:orientation="vertical">
+ <LinearLayout
+ style="@style/SectionContainer"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:weightSum="5">
+ <TextView
+ style="@style/SectionHeader"
+ android:layout_weight="1"
+ android:text="@string/section_header_job_configuration"/>
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_weight="1">
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_weight="1">
+ <TextView
+ style="@style/SpinnerLabel"
+ android:text="@string/spinner_label_network_type"/>
+ <LinearLayout
+ style="@style/SectionContainer"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent">
+ <Spinner
+ style="@style/Spinner"
+ android:id="@+id/networkType"/>
+ </LinearLayout>
+ </LinearLayout>
+ <CheckBox
+ style="@style/Checkbox"
+ android:id="@+id/requirePersistedCheckbox"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_weight="1"
+ android:text="@string/checkbox_require_persisted"/>
+ </LinearLayout>
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_weight="1"
+ android:weightSum="2">
+ <CheckBox
+ style="@style/Checkbox"
+ android:id="@+id/requireIdlenessCheckbox"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_weight="1"
+ android:text="@string/checkbox_require_idleness"/>
+ <CheckBox
+ style="@style/Checkbox"
+ android:id="@+id/requireChargingCheckbox"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_weight="1"
+ android:text="@string/checkbox_require_charging"/>
+ </LinearLayout>
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_weight="1"
+ android:orientation="horizontal">
+ <TextView
+ style="@style/SpinnerLabel"
+ android:text="@string/spinner_label_job_duration"/>
+ <LinearLayout
+ style="@style/SectionContainer"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent">
+ <Spinner
+ style="@style/Spinner"
+ android:id="@+id/jobDuration"/>
+ </LinearLayout>
+ </LinearLayout>
+ <Button
+ style="@style/Button"
+ android:id="@+id/addJobBtn"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:text="@string/button_schedule_job"
+ android:layout_weight="1"/>
+ </LinearLayout>
+ <LinearLayout
+ style="@style/SectionContainer"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:orientation="vertical">
+ <TextView
+ style="@style/SectionHeader"
+ android:text="@string/section_header_jobs_list"/>
+ <ListView
+ android:id="@+id/jobsListView"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_alignParentLeft="true"
+ android:layout_alignParentTop="true"
+ android:focusable="false"/>
+ </LinearLayout>
+ </LinearLayout>
+</LinearLayout>
\ No newline at end of file
diff --git a/tests/CarDiagnosticVerifier/res/values/strings.xml b/tests/GarageModeTestApp/res/values/colors.xml
similarity index 69%
copy from tests/CarDiagnosticVerifier/res/values/strings.xml
copy to tests/GarageModeTestApp/res/values/colors.xml
index ca6b33a..a962308 100644
--- a/tests/CarDiagnosticVerifier/res/values/strings.xml
+++ b/tests/GarageModeTestApp/res/values/colors.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2017 The Android Open Source Project
+<!-- Copyright (C) 2018 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.
@@ -14,7 +14,7 @@
limitations under the License.
-->
<resources>
- <string name="status_receiving">Receiving car diagnostic events...</string>
- <string name="status_verifying">Verifying car diagnostic events...</string>
- <string name="status_done">Done with verification</string>
+ <color name="colorPrimary">#3F51B5</color>
+ <color name="colorPrimaryDark">#303F9F</color>
+ <color name="colorAccent">#FF4081</color>
</resources>
diff --git a/tests/GarageModeTestApp/res/values/strings.xml b/tests/GarageModeTestApp/res/values/strings.xml
new file mode 100644
index 0000000..7ad5d70
--- /dev/null
+++ b/tests/GarageModeTestApp/res/values/strings.xml
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 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="app_name">GarageMode Test App</string>
+
+ <string name="button_schedule_job">Schedule Job</string>
+ <string name="button_job_info">Job Info</string>
+ <string name="button_enter_garage_mode">Enter GarageMode</string>
+ <string name="button_exit_garage_mode">Exit GarageMode</string>
+
+ <string name="checkbox_require_persisted">Persisted?</string>
+ <string name="checkbox_require_idleness">Require idleness?</string>
+ <string name="checkbox_require_charging">Require charging?</string>
+
+ <string name="no_results">No Results</string>
+
+ <string name="section_header_garage_mode_config">GarageMode Settings</string>
+ <string name="section_header_job_configuration">Job Configuration</string>
+ <string name="section_header_jobs_list">Scheduled Jobs</string>
+ <string name="section_header_watchdog">Watchdog</string>
+
+ <string name="spinner_label_garage_mode_duration">GarageMode max duration:</string>
+ <string name="spinner_label_job_duration">Job duration:</string>
+ <string name="spinner_label_network_type">Network type:</string>
+
+ <string-array name="network_types_list">
+ <item>ANY</item>
+ <item>NONE</item>
+ <item>UNMETERED</item>
+ </string-array>
+
+ <string-array name="duration_list">
+ <item>1 second</item>
+ <item>5 seconds</item>
+ <item>10 seconds</item>
+ <item>30 seconds</item>
+ <item>1 minute</item>
+ <item>5 minutes</item>
+ <item>1 hour</item>
+ </string-array>
+</resources>
diff --git a/tests/GarageModeTestApp/res/values/styles.xml b/tests/GarageModeTestApp/res/values/styles.xml
new file mode 100644
index 0000000..92cb1c5
--- /dev/null
+++ b/tests/GarageModeTestApp/res/values/styles.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 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>
+ <style name="GarageModeTheme" parent="Theme.Car.Light.NoActionBar.Drawer">
+ <item name="android:textSize">24sp</item>
+ </style>
+ <style name="SectionContainer">
+ <!-- Customize your theme here. -->
+ <item name="android:background">@drawable/border</item>
+ <item name="android:padding">3dp</item>
+ <item name="android:layout_margin">5dp</item>
+ </style>
+ <style name="Button">
+ <item name="android:layout_margin">5dp</item>
+ </style>
+ <style name="Checkbox">
+ <item name="android:background">@drawable/border</item>
+ </style>
+ <style name="SpinnerLabel">
+ <item name="android:layout_width">wrap_content</item>
+ <item name="android:textStyle">bold</item>
+ <item name="android:gravity">center_vertical|end</item>
+ <item name="android:layout_height">match_parent</item>
+ </style>
+ <style name="Spinner">
+ <item name="android:layout_width">wrap_content</item>
+ <item name="android:layout_height">match_parent</item>
+ </style>
+ <style name="SectionHeader">
+ <item name="android:layout_width">match_parent</item>
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:textStyle">bold</item>
+ <item name="android:textSize">26sp</item>
+ <item name="android:layout_marginBottom">5dp</item>
+ <item name="android:gravity">center</item>
+ </style>
+ <style name="ListEntryField">
+ <item name="android:background">@drawable/border</item>
+ <item name="android:textSize">18sp</item>
+ <item name="android:scrollHorizontally">false</item>
+ <item name="android:layout_margin">5dp</item>
+ <item name="android:padding">3dp</item>
+ </style>
+</resources>
\ No newline at end of file
diff --git a/tests/GarageModeTestApp/src/com/google/android/car/garagemode/testapp/CarIdlenessTrackerWrapper.java b/tests/GarageModeTestApp/src/com/google/android/car/garagemode/testapp/CarIdlenessTrackerWrapper.java
new file mode 100644
index 0000000..82a97e0
--- /dev/null
+++ b/tests/GarageModeTestApp/src/com/google/android/car/garagemode/testapp/CarIdlenessTrackerWrapper.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2018 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.garagemode.testapp;
+
+import android.content.Context;
+import android.content.Intent;
+
+/**
+ * Class that works with com.android.server.job.controller.idle.CarDeviceIdlenessTracker
+ */
+public class CarIdlenessTrackerWrapper {
+ public static final Logger LOG = new Logger("CarIdlenessTrackerWrapper");
+
+ public static final String ACTION_GARAGE_MODE_ON =
+ "com.android.server.jobscheduler.GARAGE_MODE_ON";
+ public static final String ACTION_GARAGE_MODE_OFF =
+ "com.android.server.jobscheduler.GARAGE_MODE_OFF";
+
+ public static final String ACTION_FORCE_IDLE = "com.android.server.jobscheduler.FORCE_IDLE";
+ public static final String ACTION_UNFORCE_IDLE = "com.android.server.jobscheduler.UNFORCE_IDLE";
+
+ public static void sendBroadcastToEnterGarageMode(Context context) {
+ Intent i = new Intent();
+ i.setAction(ACTION_GARAGE_MODE_ON);
+ i.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_NO_ABORT);
+ context.sendBroadcast(i);
+ }
+
+ public static void sendBroadcastToExitGarageMode(Context context) {
+ Intent i = new Intent();
+ i.setAction(ACTION_GARAGE_MODE_OFF);
+ i.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_NO_ABORT);
+ context.sendBroadcast(i);
+ }
+}
diff --git a/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/job/DishService.java b/tests/GarageModeTestApp/src/com/google/android/car/garagemode/testapp/DishService.java
similarity index 76%
rename from tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/job/DishService.java
rename to tests/GarageModeTestApp/src/com/google/android/car/garagemode/testapp/DishService.java
index c2758a8..5a87771 100644
--- a/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/job/DishService.java
+++ b/tests/GarageModeTestApp/src/com/google/android/car/garagemode/testapp/DishService.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015 The Android Open Source Project
+ * Copyright (C) 2018 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.
@@ -13,20 +13,19 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.google.android.car.kitchensink.job;
+package com.google.android.car.garagemode.testapp;
import android.app.job.JobParameters;
import android.app.job.JobService;
import android.os.AsyncTask;
import android.os.Handler;
import android.os.Message;
-import android.util.Log;
import android.util.SparseArray;
import java.lang.ref.WeakReference;
public class DishService extends JobService {
- private static final String TAG = "JobScheduler_DishService";
+ private static final Logger LOG = new Logger("JobScheduler_DishService");
private static final int DELAY_MS = 1000; // wash a plate every second!
private static final int MSG_FINISHED = 0;
@@ -36,13 +35,13 @@
public static final String EXTRA_DISH_COUNT = "dish_count";
private final Handler mHandler = new Handler() {
- private SparseArray<JobParameters> mTaskMap = new SparseArray<JobParameters>();
+ private SparseArray<JobParameters> mTaskMap = new SparseArray<>();
@Override
public void handleMessage(Message msg) {
JobParameters job = (JobParameters) msg.obj;
switch (msg.what) {
case MSG_FINISHED:
- Log.d(TAG, "Job done! " + job.getJobId());
+ LOG.d("Job done! " + job.getJobId());
mTaskMap.remove(job.getJobId());
jobFinished(job, false);
break;
@@ -55,19 +54,19 @@
JobParameters job1 = mTaskMap.get(job.getJobId());
if (job1 != null) {
removeMessages(MSG_RUN_JOB, job1);
- Log.d(TAG, "cancelled job " + job1);
+ LOG.d("cancelled job " + job1);
mTaskMap.remove(job.getJobId());
}
break;
default:
- Log.w(TAG, "Unknown message " + msg.what);
+ LOG.w("Unknown message " + msg.what);
}
}
};
@Override
public boolean onStopJob(JobParameters jobParameters) {
- Log.d(TAG, "onStopJob " + jobParameters);
+ LOG.d("onStopJob " + jobParameters);
Message msg = mHandler.obtainMessage(MSG_CANCEL_JOB, 0, 0, jobParameters);
mHandler.sendMessage(msg);
return false;
@@ -75,7 +74,7 @@
@Override
public boolean onStartJob(final JobParameters jobParameters) {
- Log.d(TAG, "onStartJob " + jobParameters);
+ LOG.d("onStartJob " + jobParameters);
Message msg = mHandler.obtainMessage(MSG_RUN_JOB, 0, 0, jobParameters);
mHandler.sendMessage(msg);
return true;
@@ -87,7 +86,7 @@
private final int mMyDishNum;
- public DishWasherTask(Handler handler, JobParameters jobParameters, int dishNum) {
+ DishWasherTask(Handler handler, JobParameters jobParameters, int dishNum) {
mHandler = new WeakReference<Handler>(handler);
mJobParameter = jobParameters;
mMyDishNum = dishNum;
@@ -97,7 +96,7 @@
protected Boolean doInBackground(Void... infos) {
int dishTotal = mJobParameter.getExtras().getInt(EXTRA_DISH_COUNT);
- Log.d(TAG, "jobId: " + mJobParameter.getJobId() + " totalDish: " + dishTotal
+ LOG.d("jobId: " + mJobParameter.getJobId() + " totalDish: " + dishTotal
+ " washing: #" + mMyDishNum);
wash();
if (mMyDishNum >= dishTotal - 1) {
@@ -109,17 +108,16 @@
@Override
protected void onPostExecute(Boolean result) {
- if (mHandler.get() == null) {
+ final Handler handler = mHandler.get();
+ if (handler == null) {
return;
}
if (result) {
- Message msg = mHandler.get().obtainMessage(MSG_RUN_JOB,
- mMyDishNum +1, 0, mJobParameter);
- mHandler.get().sendMessageDelayed(msg, DELAY_MS);
+ Message msg = handler.obtainMessage(MSG_RUN_JOB, mMyDishNum + 1, 0, mJobParameter);
+ handler.sendMessageDelayed(msg, DELAY_MS);
} else {
- Message msg = mHandler.get().obtainMessage(MSG_FINISHED, 0,
- 0, mJobParameter);
- mHandler.get().sendMessage(msg);
+ Message msg = handler.obtainMessage(MSG_FINISHED, 0, 0, mJobParameter);
+ handler.sendMessage(msg);
}
}
diff --git a/tests/GarageModeTestApp/src/com/google/android/car/garagemode/testapp/IncarTestingFragment.java b/tests/GarageModeTestApp/src/com/google/android/car/garagemode/testapp/IncarTestingFragment.java
new file mode 100644
index 0000000..22b460e
--- /dev/null
+++ b/tests/GarageModeTestApp/src/com/google/android/car/garagemode/testapp/IncarTestingFragment.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2018 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.garagemode.testapp;
+
+import androidx.fragment.app.Fragment;
+
+public class IncarTestingFragment extends Fragment {
+
+}
diff --git a/tests/GarageModeTestApp/src/com/google/android/car/garagemode/testapp/JobInfoRowArrayAdapter.java b/tests/GarageModeTestApp/src/com/google/android/car/garagemode/testapp/JobInfoRowArrayAdapter.java
new file mode 100644
index 0000000..0e26fe7
--- /dev/null
+++ b/tests/GarageModeTestApp/src/com/google/android/car/garagemode/testapp/JobInfoRowArrayAdapter.java
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2018 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.garagemode.testapp;
+
+import static android.graphics.Typeface.BOLD;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING;
+import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
+
+import android.app.job.JobInfo;
+import android.content.Context;
+import android.graphics.Color;
+import android.net.NetworkRequest;
+import android.text.Spannable;
+import android.text.SpannableStringBuilder;
+import android.text.style.ForegroundColorSpan;
+import android.text.style.StyleSpan;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
+import android.widget.TextView;
+
+import java.util.List;
+
+public class JobInfoRowArrayAdapter extends ArrayAdapter<JobInfo> {
+ public static final Logger LOG = new Logger("JobInfoRowArrayAdapter");
+ private class ViewHolder {
+ TextView mJobIDView;
+
+ TextView mRequiredNetworkView;
+ TextView mIsPeriodicView;
+ TextView mIsPersistedView;
+ TextView mIsPrefetchView;
+
+ TextView mIsRequireBatteryNotLowView;
+ TextView mIsRequireChargingView;
+ TextView mIsRequireDeviceIdleView;
+ TextView mIsRequireStorageNotLowView;
+
+ JobInfo mInfo;
+ }
+ private LayoutInflater mInflater;
+
+ public JobInfoRowArrayAdapter(Context context, int resource, List<JobInfo> objects) {
+ super(context, resource, objects);
+ mInflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ View row = convertView;
+ final JobInfo info = getItem(position);
+
+ ViewHolder holder;
+
+ if (row == null) {
+ row = mInflater.inflate(R.layout.job_info_row, parent, false);
+
+ holder = new ViewHolder();
+ holder.mJobIDView = row.findViewById(R.id.jobId);
+
+ holder.mRequiredNetworkView = row.findViewById(R.id.requiredNetwork);
+ holder.mIsPeriodicView = row.findViewById(R.id.isPeriodic);
+ holder.mIsPersistedView = row.findViewById(R.id.isPersisted);
+ holder.mIsPrefetchView = row.findViewById(R.id.isPrefetch);
+
+ holder.mIsRequireBatteryNotLowView = row.findViewById(R.id.isRequireBatteryNotLow);
+ holder.mIsRequireChargingView = row.findViewById(R.id.isRequireCharging);
+ holder.mIsRequireDeviceIdleView = row.findViewById(R.id.isRequireDeviceIdle);
+ holder.mIsRequireStorageNotLowView = row.findViewById(R.id.isRequireStorageNotLow);
+
+ holder.mInfo = info;
+
+ row.setTag(holder);
+ } else {
+ holder = (ViewHolder) row.getTag();
+ holder.mInfo = info;
+ }
+
+ holder.mJobIDView.setText("ID: " + info.getId());
+
+ setNetworkColoredText(holder.mRequiredNetworkView, "Network", info.getRequiredNetwork());
+
+ setColoredText(holder.mIsPeriodicView, "Periodic", info.isPeriodic());
+ setColoredText(holder.mIsPersistedView, "Persisted", info.isPersisted());
+ setColoredText(holder.mIsPrefetchView, "Prefetch", info.isPrefetch());
+
+ setColoredText(
+ holder.mIsRequireBatteryNotLowView,
+ "BatteryNotLow",
+ info.isRequireBatteryNotLow());
+ setColoredText(holder.mIsRequireChargingView, "Charging", info.isRequireCharging());
+ setColoredText(holder.mIsRequireDeviceIdleView, "DeviceIdle", info.isRequireDeviceIdle());
+ setColoredText(
+ holder.mIsRequireStorageNotLowView,
+ "StorageNotLow",
+ info.isRequireStorageNotLow());
+
+ return row;
+ }
+
+ private void setColoredText(TextView view, String label, boolean condition) {
+ SpannableStringBuilder sb;
+ String value = (condition ? "Yes" : "No");
+ int color = (condition ? Color.GREEN : Color.RED);
+ sb = new SpannableStringBuilder(label + ": " + value);
+ applyColorAndBoldness(
+ sb, color, label.length() + 2, label.length() + 2 + value.length());
+ view.setText(sb);
+ }
+
+ private void setNetworkColoredText(TextView view, String label, NetworkRequest networkReq) {
+ String networkType = getNetworkType(networkReq);
+ SpannableStringBuilder sb = new SpannableStringBuilder(label + ": " + networkType);
+ applyColorAndBoldness(
+ sb, Color.GREEN, label.length() + 2, label.length() + 2 + networkType.length());
+ view.setText(sb);
+ }
+
+ private void applyColorAndBoldness(SpannableStringBuilder sb, int color, int start, int end) {
+ sb.setSpan(new ForegroundColorSpan(color), start, end, Spannable.SPAN_INCLUSIVE_INCLUSIVE);
+ sb.setSpan(new StyleSpan(BOLD), start, end, Spannable.SPAN_INCLUSIVE_INCLUSIVE);
+ }
+
+ private String getNetworkType(NetworkRequest networkRequest) {
+ if (networkRequest == null) {
+ return "None";
+ } else if (networkRequest.networkCapabilities.hasCapability(NET_CAPABILITY_NOT_METERED)) {
+ return "Unmetered";
+ } else if (networkRequest.networkCapabilities.hasCapability(NET_CAPABILITY_NOT_ROAMING)) {
+ return "Not roaming";
+ } else if (networkRequest.networkCapabilities.hasTransport(TRANSPORT_CELLULAR)) {
+ return "Cellular";
+ } else {
+ return "Any";
+ }
+ }
+}
diff --git a/tests/GarageModeTestApp/src/com/google/android/car/garagemode/testapp/JobSchedulerWrapper.java b/tests/GarageModeTestApp/src/com/google/android/car/garagemode/testapp/JobSchedulerWrapper.java
new file mode 100644
index 0000000..a2d1edd
--- /dev/null
+++ b/tests/GarageModeTestApp/src/com/google/android/car/garagemode/testapp/JobSchedulerWrapper.java
@@ -0,0 +1,242 @@
+/*
+ * Copyright (C) 2018 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.garagemode.testapp;
+
+import android.app.job.JobInfo;
+import android.app.job.JobScheduler;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.os.Handler;
+import android.os.PersistableBundle;
+import android.widget.ListView;
+import android.widget.Toast;
+
+import java.util.LinkedList;
+import java.util.List;
+
+class JobSchedulerWrapper {
+ private static final Logger LOG = new Logger("JobSchedulerWrapper");
+ private static final boolean DEBUG = false;
+
+ private static final String ANDROID_COMPONENT_PREFIX = "android/com.android.";
+ private static final String ANDROID_SETTINGS_PREFIX =
+ "com.android.settings/com.android.settings.";
+
+ private static final String PREFS_FILE_NAME = "garage_mode_job_scheduler";
+ private static final String PREFS_NEXT_JOB_ID = "next_job_id";
+
+ private JobScheduler mJobScheduler;
+ private Context mContext;
+ private ListView mListView;
+ private Handler mHandler;
+ private Watchdog mWatchdog;
+ private Runnable mRefreshWorker;
+
+ private List<JobInfo> mLastJobsList;
+ private List<JobInfo> mNewJobs;
+ private List<JobInfo> mCompletedJobs;
+ private JobInfoRowArrayAdapter mJobsListAdapter;
+
+ JobSchedulerWrapper(Context context, ListView listView) {
+ mContext = context;
+ mJobScheduler = (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
+ mListView = listView;
+
+ mLastJobsList = new LinkedList<>();
+ mNewJobs = new LinkedList<>();
+ mCompletedJobs = new LinkedList<>();
+ mJobsListAdapter = new JobInfoRowArrayAdapter(mContext, mListView.getId(), mLastJobsList);
+ mListView.setAdapter(mJobsListAdapter);
+
+ updateJobs();
+ if (DEBUG) {
+ printJobsOnce(mJobScheduler.getAllPendingJobs());
+ }
+ }
+
+ public void setWatchdog(Watchdog watchdog) {
+ mWatchdog = watchdog;
+ }
+
+ public synchronized void refresh() {
+ updateJobs();
+
+ reportNewJobs();
+ reportCompletedJobs();
+
+ if (mNewJobs.size() > 0 || mCompletedJobs.size() > 0) {
+ updateListView();
+ }
+ }
+
+ public void start() {
+ LOG.d("Starting JobSchedulerWrapper");
+ mHandler = new Handler();
+ mRefreshWorker = () -> {
+ refresh();
+ mHandler.postDelayed(mRefreshWorker, 1000);
+ };
+ mHandler.postDelayed(mRefreshWorker, 1000);
+ }
+
+ public void stop() {
+ LOG.d("Stopping JobSchedulerWrapper");
+ mHandler.removeCallbacks(mRefreshWorker);
+ mRefreshWorker = null;
+ mHandler = null;
+ mWatchdog = null;
+ }
+
+ public void scheduleAJob(
+ int amountOfSeconds,
+ int networkType,
+ boolean isChargingRequired,
+ boolean isIdleRequired) {
+ ComponentName jobComponentName = new ComponentName(mContext, DishService.class);
+ SharedPreferences prefs = mContext
+ .getSharedPreferences(PREFS_FILE_NAME, Context.MODE_PRIVATE);
+ int jobId = prefs.getInt(PREFS_NEXT_JOB_ID, 0);
+ PersistableBundle bundle = new PersistableBundle();
+
+ bundle.putInt(DishService.EXTRA_DISH_COUNT, amountOfSeconds);
+
+ while (checkIdForExistence(jobId)) {
+ jobId++;
+ }
+
+ JobInfo jobInfo = new JobInfo.Builder(jobId, jobComponentName)
+ .setRequiresCharging(isChargingRequired)
+ .setRequiresDeviceIdle(isIdleRequired)
+ .setExtras(bundle)
+ .setRequiredNetworkType(networkType)
+ .build();
+
+ mJobScheduler.schedule(jobInfo);
+ Toast.makeText(
+ mContext,
+ "Scheduled new job with id: " + jobInfo.getId(), Toast.LENGTH_LONG).show();
+
+ LOG.d("Scheduled a job: " + jobInfo);
+ SharedPreferences.Editor editor = prefs.edit();
+ editor.putInt(PREFS_NEXT_JOB_ID, jobId + 1);
+ editor.commit();
+
+ refresh();
+ }
+
+ private void updateListView() {
+ int index = mListView.getFirstVisiblePosition();
+ mJobsListAdapter.notifyDataSetChanged();
+ mListView.smoothScrollToPosition(index);
+ }
+
+ private boolean checkIdForExistence(int jobId) {
+ for (JobInfo job : mJobScheduler.getAllPendingJobs()) {
+ if (job.getId() == jobId) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private void printJobsOnce(List<JobInfo> list) {
+ LOG.d("=========================================================");
+ for (JobInfo job : list) {
+ LOG.d("Job(" + job.getId() + ") will run " + job.getService());
+ }
+ }
+
+ private void reportNewJobs() {
+ for (JobInfo job : mNewJobs) {
+ if (mWatchdog != null) {
+ mWatchdog.logEvent("New job with id(" + job.getId() + ") has been scheduled");
+ }
+ }
+ }
+
+ private void reportCompletedJobs() {
+ for (JobInfo job : mCompletedJobs) {
+ if (mWatchdog != null) {
+ mWatchdog.logEvent("Job with id(" + job.getId() + ") has been completed.");
+ }
+ }
+ }
+
+ private synchronized void updateJobs() {
+ List<JobInfo> currentJobs = mJobScheduler.getAllPendingJobs();
+
+ if (DEBUG) {
+ printJobsOnce(currentJobs);
+ printJobsOnce(mLastJobsList);
+ }
+
+ removeSystemJobsFromList(currentJobs);
+
+ mNewJobs = newJobsSince(mLastJobsList, currentJobs);
+ mCompletedJobs = completedJobsSince(mLastJobsList, currentJobs);
+
+ for (JobInfo job : mNewJobs) {
+ mLastJobsList.add(job);
+ }
+
+ for (JobInfo job : mCompletedJobs) {
+ mLastJobsList.remove(job);
+ }
+ }
+
+ private synchronized List<JobInfo> newJobsSince(List<JobInfo> oldList, List<JobInfo> newList) {
+ return findDiffBetween(newList, oldList);
+ }
+
+ private synchronized List<JobInfo> completedJobsSince(
+ List<JobInfo> oldList, List<JobInfo> newList) {
+ return findDiffBetween(oldList, newList);
+ }
+
+ private synchronized List<JobInfo> findDiffBetween(
+ List<JobInfo> fromList, List<JobInfo> toList) {
+ List<JobInfo> diffList = new LinkedList<>();
+ for (JobInfo fromJob : fromList) {
+ if (!toList.contains(fromJob)) {
+ diffList.add(fromJob);
+ }
+ }
+ return diffList;
+ }
+
+ private synchronized void removeSystemJobsFromList(List<JobInfo> list) {
+ List<JobInfo> jobsToRemove = new LinkedList<>();
+ for (JobInfo job : list) {
+ if (isSystemService(job)) {
+ jobsToRemove.add(job);
+ }
+ }
+ for (JobInfo job : jobsToRemove) {
+ list.remove(job);
+ }
+ }
+
+ private boolean isSystemService(JobInfo job) {
+ if (job.getService().toString().contains(ANDROID_COMPONENT_PREFIX)) {
+ return true;
+ }
+ if (job.getService().toString().contains(ANDROID_SETTINGS_PREFIX)) {
+ return true;
+ }
+ return false;
+ }
+}
diff --git a/tests/GarageModeTestApp/src/com/google/android/car/garagemode/testapp/Logger.java b/tests/GarageModeTestApp/src/com/google/android/car/garagemode/testapp/Logger.java
new file mode 100644
index 0000000..192eec3
--- /dev/null
+++ b/tests/GarageModeTestApp/src/com/google/android/car/garagemode/testapp/Logger.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2018 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.garagemode.testapp;
+
+import android.util.Log;
+
+class Logger {
+ private final String mTag;
+ private final String mPrefix;
+
+ Logger(String prefix) {
+ mTag = "GarageModeTestApp";
+ mPrefix = prefix;
+ }
+
+ /** Passing message further to Log.v() */
+ public void v(String msg) {
+ Log.v(mTag, buildMessage(msg));
+ }
+
+ /** Passing message further to Log.v() */
+ public void v(String msg, Exception ex) {
+ Log.v(mTag, buildMessage(msg), ex);
+ }
+
+ /** Passing message further to Log.i() */
+ public void i(String msg) {
+ Log.i(mTag, buildMessage(msg));
+ }
+
+ /** Passing message further to Log.i() */
+ public void i(String msg, Exception ex) {
+ Log.i(mTag, buildMessage(msg), ex);
+ }
+
+ /** Passing message further to Log.d() */
+ public void d(String msg) {
+ Log.d(mTag, buildMessage(msg));
+ }
+
+ /** Passing message further to Log.d() */
+ public void d(String msg, Exception ex) {
+ Log.d(mTag, buildMessage(msg), ex);
+ }
+
+ /** Passing message further to Log.w() */
+ public void w(String msg, Exception ex) {
+ Log.w(mTag, buildMessage(msg), ex);
+ }
+
+ /** Passing message further to Log.w() */
+ public void w(String msg) {
+ Log.w(mTag, buildMessage(msg));
+ }
+
+ /** Passing message further to Log.e() */
+ public void e(String msg) {
+ Log.e(mTag, buildMessage(msg));
+ }
+
+ /** Passing message further to Log.e() */
+ public void e(String msg, Exception ex) {
+ Log.e(mTag, buildMessage(msg), ex);
+ }
+
+ /** Passing message further to Log.e() */
+ public void wtf(String msg) {
+ Log.wtf(mTag, buildMessage(msg));
+ }
+
+ /** Passing message further to Log.e() */
+ public void wtf(String msg, Exception ex) {
+ Log.wtf(mTag, buildMessage(msg), ex);
+ }
+
+ private String buildMessage(String msg) {
+ return String.format("[%s]: %s", mPrefix, msg);
+ }
+}
diff --git a/tests/GarageModeTestApp/src/com/google/android/car/garagemode/testapp/MainActivity.java b/tests/GarageModeTestApp/src/com/google/android/car/garagemode/testapp/MainActivity.java
new file mode 100644
index 0000000..410b9eb
--- /dev/null
+++ b/tests/GarageModeTestApp/src/com/google/android/car/garagemode/testapp/MainActivity.java
@@ -0,0 +1,166 @@
+/*
+ * Copyright (C) 2018 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.garagemode.testapp;
+
+import android.os.Bundle;
+
+import androidx.car.drawer.CarDrawerActivity;
+import androidx.car.drawer.CarDrawerAdapter;
+import androidx.car.drawer.DrawerItemViewHolder;
+import androidx.fragment.app.Fragment;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class MainActivity extends CarDrawerActivity {
+ private static final Logger LOG = new Logger("MainActivity");
+
+ private final List<MenuEntry> mMenuEntries = new ArrayList<MenuEntry>() {
+ {
+ add("Offcar testing", OffcarTestingFragment.class);
+ add("Incar testing", IncarTestingFragment.class);
+ add("Quit", MainActivity.this::finish);
+ }
+
+ <T extends Fragment> void add(String text, Class<T> clazz) {
+ add(new FragmentMenuEntry(text, clazz));
+ }
+
+ void add(String text, ClickHandler onClick) {
+ add(new OnClickMenuEntry(text, onClick));
+ }
+ };
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setMainContent(R.layout.activity_content);
+ mMenuEntries.get(0).onClick();
+ }
+
+ @Override
+ protected CarDrawerAdapter getRootAdapter() {
+ return new DrawerAdapter();
+ }
+
+ private interface ClickHandler {
+ void onClick();
+ }
+
+ private abstract static class MenuEntry implements ClickHandler {
+ abstract String getText();
+ }
+
+ private final class OnClickMenuEntry extends MenuEntry {
+ private final String mText;
+ private final ClickHandler mClickHandler;
+
+ OnClickMenuEntry(String text, ClickHandler clickHandler) {
+ mText = text;
+ mClickHandler = clickHandler;
+ }
+
+ @Override
+ String getText() {
+ return mText;
+ }
+
+ @Override
+ public void onClick() {
+ mClickHandler.onClick();
+ }
+ }
+
+ private final class FragmentMenuEntry<T extends Fragment> extends MenuEntry {
+ private final class FragmentClassOrInstance<T extends Fragment> {
+ final Class<T> mClazz;
+ T mFragment = null;
+
+ FragmentClassOrInstance(Class<T> clazz) {
+ mClazz = clazz;
+ }
+
+ T getFragment() {
+ if (mFragment == null) {
+ try {
+ mFragment = mClazz.newInstance();
+ } catch (InstantiationException | IllegalAccessException e) {
+ LOG.e("unable to create fragment", e);
+ }
+ }
+ return mFragment;
+ }
+ }
+
+ private final String mText;
+ private final FragmentClassOrInstance<T> mFragment;
+
+ FragmentMenuEntry(String text, Class<T> clazz) {
+ mText = text;
+ mFragment = new FragmentClassOrInstance<>(clazz);
+ }
+
+ @Override
+ String getText() {
+ return mText;
+ }
+
+ @Override
+ public void onClick() {
+ Fragment fragment = mFragment.getFragment();
+ if (fragment != null) {
+ MainActivity.this.showFragment(fragment);
+ } else {
+ LOG.e("cannot show fragment for " + getText());
+ }
+ }
+ }
+
+ private void showFragment(Fragment fragment) {
+ getSupportFragmentManager().beginTransaction()
+ .replace(R.id.activity_content, fragment)
+ .commit();
+ }
+
+ private final class DrawerAdapter extends CarDrawerAdapter {
+ DrawerAdapter() {
+ super(MainActivity.this, true /* showDisabledOnListOnEmpty */);
+ setTitle(getString(R.string.app_name));
+ }
+
+ @Override
+ protected int getActualItemCount() {
+ return mMenuEntries.size();
+ }
+
+ @Override
+ protected void populateViewHolder(DrawerItemViewHolder holder, int position) {
+ holder.getTitleView().setText(mMenuEntries.get(position).getText());
+ holder.itemView.setOnClickListener(v -> onItemClick(holder.getAdapterPosition()));
+ }
+
+ private void onItemClick(int position) {
+ if ((position < 0) || (position >= mMenuEntries.size())) {
+ LOG.wtf("Unknown menu item: " + position);
+ return;
+ }
+
+ mMenuEntries.get(position).onClick();
+
+ getDrawerController().closeDrawer();
+ }
+ }
+}
diff --git a/tests/GarageModeTestApp/src/com/google/android/car/garagemode/testapp/OffcarTestingFragment.java b/tests/GarageModeTestApp/src/com/google/android/car/garagemode/testapp/OffcarTestingFragment.java
new file mode 100644
index 0000000..6d7a8ce
--- /dev/null
+++ b/tests/GarageModeTestApp/src/com/google/android/car/garagemode/testapp/OffcarTestingFragment.java
@@ -0,0 +1,219 @@
+/*
+ * Copyright (C) 2018 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.garagemode.testapp;
+
+import android.app.job.JobInfo;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.Button;
+import android.widget.CheckBox;
+import android.widget.ListView;
+import android.widget.Spinner;
+import android.widget.TextView;
+
+import androidx.annotation.Nullable;
+import androidx.fragment.app.Fragment;
+
+public class OffcarTestingFragment extends Fragment implements AdapterView.OnItemSelectedListener {
+ private static final Logger LOG = new Logger("OffcarTestingFragment");
+
+ private String mNetworkRequirement;
+ private int mJobDurationSelected;
+
+ private CheckBox mRequirePersisted;
+ private CheckBox mRequireIdleness;
+ private CheckBox mRequireCharging;
+
+ private Spinner mJobDurationSpinner;
+ private Spinner mNetworkTypeSpinner;
+
+ private TextView mWatchdogTextView;
+ private ListView mJobsListView;
+
+ private Button mEnterGarageModeBtn;
+ private Button mExitGarageModeBtn;
+ private Button mAddJobBtn;
+
+ private Watchdog mWatchdog;
+ private JobSchedulerWrapper mJobSchedulerWrapper;
+
+ @Nullable
+ @Override
+ public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
+ @Nullable Bundle savedInstanceState) {
+ View v = inflater.inflate(R.layout.offcar_testing, container, false);
+
+ defineViewsFromFragment(v);
+
+ populateNetworkTypeSpinner();
+ populateJobDurationSpinner();
+
+ defineButtonActions();
+
+ return v;
+ }
+
+ @Override
+ public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
+ String value = (String) parent.getItemAtPosition(pos);
+ switch (parent.getId()) {
+ case R.id.networkType:
+ applyNetworkTypeRequirement(value);
+ break;
+ case R.id.jobDuration:
+ applyJobDuration(value);
+ break;
+ }
+ }
+
+ @Override
+ public void onNothingSelected(AdapterView<?> adapterView) {
+
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ LOG.d("Resuming app");
+
+ mWatchdog = new Watchdog(getContext(), mWatchdogTextView);
+ mWatchdog.start();
+ mJobSchedulerWrapper = new JobSchedulerWrapper(
+ getContext(),
+ mJobsListView);
+ mJobSchedulerWrapper.setWatchdog(mWatchdog);
+ mJobSchedulerWrapper.start();
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ LOG.d("Pausing app");
+ mWatchdog.stop();
+ mWatchdog = null;
+ mJobSchedulerWrapper.stop();
+ mJobSchedulerWrapper = null;
+ }
+
+ private void defineViewsFromFragment(View v) {
+ mRequirePersisted = v.findViewById(R.id.requirePersistedCheckbox);
+ mRequireIdleness = v.findViewById(R.id.requireIdlenessCheckbox);
+ mRequireCharging = v.findViewById(R.id.requireChargingCheckbox);
+
+ mJobDurationSpinner = v.findViewById(R.id.jobDuration);
+ mNetworkTypeSpinner = v.findViewById(R.id.networkType);
+
+ mWatchdogTextView = v.findViewById(R.id.garageModeWatchdog);
+ mJobsListView = v.findViewById(R.id.jobsListView);
+
+ mEnterGarageModeBtn = v.findViewById(R.id.enterGarageModeBtn);
+ mExitGarageModeBtn = v.findViewById(R.id.exitGarageModeBtn);
+ mAddJobBtn = v.findViewById(R.id.addJobBtn);
+ }
+
+ private void defineButtonActions() {
+ mEnterGarageModeBtn.setOnClickListener(view -> onEnterGarageModeBtnClick());
+ mExitGarageModeBtn.setOnClickListener(view -> onExitGarageModeBtnClick());
+ mAddJobBtn.setOnClickListener(view -> onAddJobBtnClick());
+ }
+
+ private void onEnterGarageModeBtnClick() {
+ LOG.d("Entering garage mode...");
+ CarIdlenessTrackerWrapper.sendBroadcastToEnterGarageMode(getContext());
+ if (mWatchdog != null) {
+ mWatchdog.logEvent("Entering garage mode...");
+ }
+ }
+
+ private void onExitGarageModeBtnClick() {
+ LOG.d("Exiting garage mode...");
+ CarIdlenessTrackerWrapper.sendBroadcastToExitGarageMode(getContext());
+ if (mWatchdog != null) {
+ mWatchdog.logEvent("Exiting garage mode...");
+ }
+ }
+
+ private void onAddJobBtnClick() {
+ LOG.d("Adding a job...");
+ if (mJobSchedulerWrapper == null) {
+ LOG.e("JobSchedulerWrapper is not initialized yet. Try again later.");
+ return;
+ }
+ mJobSchedulerWrapper.scheduleAJob(
+ mJobDurationSelected,
+ parseNetworkRequirement(),
+ mRequireCharging.isChecked(),
+ mRequireIdleness.isChecked());
+ }
+
+ private void applyJobDuration(String value) {
+ String metric = value.split(" ")[1];
+ mJobDurationSelected = Integer.parseInt(value.split(" ")[0]);
+ if (metric.startsWith("minute")) {
+ mJobDurationSelected *= 60;
+ }
+ if (metric.startsWith("hour")) {
+ mJobDurationSelected *= 3600;
+ }
+ mWatchdog.logEvent("Job duration is now: " + mJobDurationSelected + "s");
+ }
+
+ private void applyNetworkTypeRequirement(String value) {
+ mNetworkRequirement = value;
+ mWatchdog.logEvent("Job network requirement changed to: " + value);
+ }
+
+ private int parseNetworkRequirement() {
+ if (mNetworkRequirement.equals("NONE")) {
+ return JobInfo.NETWORK_TYPE_NONE;
+ }
+ if (mNetworkRequirement.equals("UNMETERED")) {
+ return JobInfo.NETWORK_TYPE_UNMETERED;
+ }
+ if (mNetworkRequirement.equals("ANY")) {
+ return JobInfo.NETWORK_TYPE_ANY;
+ }
+ return JobInfo.NETWORK_BYTES_UNKNOWN;
+ }
+
+ private void populateJobDurationSpinner() {
+ populateSpinner(
+ mJobDurationSpinner,
+ ArrayAdapter.createFromResource(
+ getContext(),
+ R.array.duration_list,
+ android.R.layout.simple_spinner_item));
+ }
+
+ private void populateNetworkTypeSpinner() {
+ populateSpinner(
+ mNetworkTypeSpinner,
+ ArrayAdapter.createFromResource(
+ getContext(),
+ R.array.network_types_list,
+ android.R.layout.simple_spinner_item));
+ }
+
+ private void populateSpinner(Spinner spinner, ArrayAdapter adapter) {
+ adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+ spinner.setAdapter(adapter);
+ spinner.setOnItemSelectedListener(this);
+ }
+}
diff --git a/tests/GarageModeTestApp/src/com/google/android/car/garagemode/testapp/Watchdog.java b/tests/GarageModeTestApp/src/com/google/android/car/garagemode/testapp/Watchdog.java
new file mode 100644
index 0000000..18ce8fa
--- /dev/null
+++ b/tests/GarageModeTestApp/src/com/google/android/car/garagemode/testapp/Watchdog.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2018 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.garagemode.testapp;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.os.Handler;
+import android.widget.TextView;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.LinkedList;
+
+public class Watchdog {
+ private static final Logger LOG = new Logger("Watchdog");
+
+ private static final String PREFS_FILE_NAME = "garage_mode_watchdog";
+ private static final String PREFS_EVENTS_LIST = "events_list";
+ private static final String PREFS_EVENTS_LIST_SEPARATOR = "\n";
+ // TODO(serikb): Convert TextView to ListView with per row coloring
+ private TextView mView;
+ private LinkedList<String> mEvents;
+ private Handler mWatchdogHandler;
+ private Runnable mRefreshLoop;
+ private SharedPreferences mSharedPrefs;
+
+ public Watchdog(Context context, TextView view) {
+ this(
+ context,
+ view,
+ context.getSharedPreferences(PREFS_FILE_NAME, Context.MODE_PRIVATE));
+ }
+
+ public Watchdog(Context context, TextView view, SharedPreferences prefs) {
+ mView = view;
+ mSharedPrefs = prefs;
+ mEvents = getEventsFromSharedPrefs(prefs);
+ }
+
+ public void logEvent(String s) {
+ Date date = new Date();
+ SimpleDateFormat dateFormat = new SimpleDateFormat("[yyyy-MM-dd hh:mm:ss]");
+ mEvents.addFirst(dateFormat.format(date) + " " + s);
+ if (mEvents.size() > 10000) {
+ mEvents.pollLast();
+ }
+ saveEventsToSharedPrefs(mSharedPrefs, mEvents);
+ }
+
+ public synchronized String getEventsAsText() {
+ return String.join("\n", mEvents);
+ }
+
+ public synchronized void refresh() {
+ mView.setText(getEventsAsText());
+ }
+
+ public void start() {
+ LOG.d("Starting Watchdog");
+ mWatchdogHandler = new Handler();
+ mRefreshLoop = () -> {
+ refresh();
+ mWatchdogHandler.postDelayed(mRefreshLoop, 500);
+ };
+ mWatchdogHandler.postDelayed(mRefreshLoop, 500);
+ }
+
+ public void stop() {
+ LOG.d("Stopping Watchdog");
+ mWatchdogHandler.removeCallbacks(mRefreshLoop);
+ mWatchdogHandler = null;
+ mRefreshLoop = null;
+ }
+
+ private LinkedList<String> getEventsFromSharedPrefs(SharedPreferences prefs) {
+ LinkedList<String> list = new LinkedList<>();
+ String file = prefs.getString(PREFS_EVENTS_LIST, "");
+ for (String line : file.split(PREFS_EVENTS_LIST_SEPARATOR)) {
+ list.add(line);
+ }
+ return list;
+ }
+
+ private void saveEventsToSharedPrefs(SharedPreferences prefs, LinkedList<String> list) {
+ String file = "";
+ for (String item : list) {
+ if (!file.isEmpty()) {
+ file += PREFS_EVENTS_LIST_SEPARATOR + item;
+ } else {
+ file += item;
+ }
+ }
+ SharedPreferences.Editor editor = prefs.edit();
+ editor.putString(PREFS_EVENTS_LIST, file);
+ editor.commit();
+ }
+}
diff --git a/tests/UxRestrictionsSample/AndroidManifest.xml b/tests/UxRestrictionsSample/AndroidManifest.xml
index 4c702ca..5c99038 100644
--- a/tests/UxRestrictionsSample/AndroidManifest.xml
+++ b/tests/UxRestrictionsSample/AndroidManifest.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2017 The Android Open Source Project
+<!-- Copyright (C) 2018 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.
@@ -14,9 +14,9 @@
limitations under the License.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.google.android.car.uxr.sample" android:sharedUserId="android.uid.system">
+ package="com.google.android.car.uxr.sample" android:sharedUserId="android.uid.system">
- <uses-permission android:name="android.car.permission.CAR_DRIVING_STATE" />
+ <uses-permission android:name="android.car.permission.CAR_DRIVING_STATE"/>
<application android:label="UxRestrictions Sample">
<activity android:name=".MainActivity">
@@ -26,5 +26,9 @@
</intent-filter>
<meta-data android:name="distractionOptimized" android:value="true"/>
</activity>
+ <activity android:name=".SampleMessageActivity"
+ android:theme="@style/Theme.Car.NoActionBar">
+ <meta-data android:name="distractionOptimized" android:value="true"/>
+ </activity>
</application>
</manifest>
diff --git a/tests/UxRestrictionsSample/res/layout/activity_sample_message.xml b/tests/UxRestrictionsSample/res/layout/activity_sample_message.xml
new file mode 100644
index 0000000..20c6465
--- /dev/null
+++ b/tests/UxRestrictionsSample/res/layout/activity_sample_message.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 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.
+-->
+<androidx.car.moderator.SpeedBumpView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+ <Button
+ android:id="@+id/home_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/return_home"
+ android:textAllCaps="false"
+ android:textAppearance="?android:textAppearanceLarge"/>
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+ <androidx.car.widget.PagedListView
+ android:id="@+id/paged_list_view"
+ android:layout_height="match_parent"
+ android:layout_width="wrap_content"
+ android:layout_weight="4"/>
+ </LinearLayout>
+ </LinearLayout>
+</androidx.car.moderator.SpeedBumpView>
diff --git a/tests/UxRestrictionsSample/res/layout/main_activity.xml b/tests/UxRestrictionsSample/res/layout/main_activity.xml
index ec0d226..695e93b 100644
--- a/tests/UxRestrictionsSample/res/layout/main_activity.xml
+++ b/tests/UxRestrictionsSample/res/layout/main_activity.xml
@@ -17,7 +17,6 @@
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
-
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
@@ -27,41 +26,101 @@
android:layout_height="match_parent"
android:layout_width="0dp"
android:layout_weight="1"
- android:orientation="vertical"
- android:gravity="center">
+ android:orientation="vertical">
+
+ <TextView
+ android:text="@string/status_header"
+ android:layout_gravity="center"
+ android:padding="@dimen/section_padding"
+ android:textSize="@dimen/header_text_size"
+ android:layout_width="match_parent"
+ android:textAppearance="?android:textAppearanceLarge"
+ android:layout_height="wrap_content" />
+
<TextView
android:id="@+id/driving_state"
+ android:text="@string/driving_state"
+ android:textSize="@dimen/info_text_size"
android:layout_gravity="center"
+ android:padding="@dimen/section_padding"
android:layout_width="match_parent"
android:textAppearance="?android:textAppearanceLarge"
android:layout_height="wrap_content" />
+
<TextView
android:id="@+id/do_status"
- android:layout_gravity="center"
+ android:text="@string/is_do_reqd"
+ android:textSize="@dimen/info_text_size"
+ android:padding="@dimen/section_padding"
android:layout_width="match_parent"
android:textAppearance="?android:textAppearanceLarge"
android:layout_height="wrap_content" />
+
<TextView
android:id="@+id/uxr_status"
- android:layout_gravity="center"
+ android:text="@string/active_restrictions"
+ android:padding="@dimen/section_padding"
+ android:textSize="@dimen/info_text_size"
android:layout_width="match_parent"
android:textAppearance="?android:textAppearanceLarge"
android:layout_height="wrap_content" />
- <Button
- android:id="@+id/toggle_status"
+
+ <View
android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="Disable Ux Restrictions"
- android:textSize="32sp"/>
+ android:layout_height="1dp"
+ android:padding="@dimen/section_padding"
+ android:layout_marginBottom="10dp"
+ android:background="@android:color/darker_gray"/>
+
+ <TextView
+ android:text="@string/action_header"
+ android:padding="@dimen/section_padding"
+ android:textSize="@dimen/header_text_size"
+ android:layout_width="match_parent"
+ android:textAppearance="?android:textAppearanceLarge"
+ android:layout_height="wrap_content" />
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+ <Button
+ android:id="@+id/toggle_status"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:padding="@dimen/section_padding"
+ android:text="@string/disable_uxr"
+ android:textAllCaps="false"
+ android:textSize="@dimen/info_text_size" />
+ </LinearLayout>
+
+ <View
+ android:layout_width="match_parent"
+ android:layout_height="1dp"
+ android:layout_marginTop="@dimen/section_padding"
+ android:layout_marginBottom="10dp"
+ android:background="@android:color/darker_gray"/>
+
+ <TextView
+ android:text="@string/sample_header"
+ android:padding="@dimen/section_padding"
+ android:textSize="@dimen/header_text_size"
+ android:layout_width="match_parent"
+ android:textAppearance="?android:textAppearanceLarge"
+ android:layout_height="wrap_content" />
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+ <Button
+ android:id="@+id/launch_message"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/sample_msg_activity"
+ android:textAllCaps="false"
+ android:textSize="@dimen/info_text_size" />
+ </LinearLayout>
</LinearLayout>
-
- <androidx.car.widget.PagedListView
- android:id="@+id/paged_list_view"
- android:layout_width="0dp"
- android:layout_height="match_parent"
- android:layout_weight="4" />
</LinearLayout>
-
</androidx.car.moderator.SpeedBumpView>
diff --git a/tests/CarDiagnosticVerifier/res/values/strings.xml b/tests/UxRestrictionsSample/res/values/dimens.xml
similarity index 69%
rename from tests/CarDiagnosticVerifier/res/values/strings.xml
rename to tests/UxRestrictionsSample/res/values/dimens.xml
index ca6b33a..66f0aea 100644
--- a/tests/CarDiagnosticVerifier/res/values/strings.xml
+++ b/tests/UxRestrictionsSample/res/values/dimens.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2017 The Android Open Source Project
+<!-- Copyright (C) 2018 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.
@@ -14,7 +14,9 @@
limitations under the License.
-->
<resources>
- <string name="status_receiving">Receiving car diagnostic events...</string>
- <string name="status_verifying">Verifying car diagnostic events...</string>
- <string name="status_done">Done with verification</string>
+ <dimen name="section_padding">5dp</dimen>
+
+ <!-- Text size for the sample app -->
+ <dimen name="info_text_size">24sp</dimen>
+ <dimen name="header_text_size">32sp</dimen>
</resources>
diff --git a/tests/UxRestrictionsSample/res/values/strings.xml b/tests/UxRestrictionsSample/res/values/strings.xml
new file mode 100644
index 0000000..612e251
--- /dev/null
+++ b/tests/UxRestrictionsSample/res/values/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 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="app_name">UxRestrictionsSample</string>
+ <string name="title_activity_main">MainActivity</string>
+ <string name="status_header"><u>Current Status</u></string>
+ <string name="driving_state">Driving State: </string>
+ <string name="is_do_reqd">Distraction Optimization Required? </string>
+ <string name="active_restrictions">Active UX Restrictions: </string>
+ <string name="action_header"><u>Available Actions</u></string>
+ <string name="disable_uxr">Disable Ux Restriction Engine</string>
+ <string name="sample_header"><u>Sample Activities</u></string>
+ <string name="sample_msg_activity">Sample Message Activity</string>
+ <string name="return_home"><u>Return Home</u></string>
+</resources>
diff --git a/tests/UxRestrictionsSample/src/com/google/android/car/uxr/sample/MainActivity.java b/tests/UxRestrictionsSample/src/com/google/android/car/uxr/sample/MainActivity.java
index ba82e6f..104e145 100644
--- a/tests/UxRestrictionsSample/src/com/google/android/car/uxr/sample/MainActivity.java
+++ b/tests/UxRestrictionsSample/src/com/google/android/car/uxr/sample/MainActivity.java
@@ -15,7 +15,6 @@
*/
package com.google.android.car.uxr.sample;
-import android.annotation.DrawableRes;
import android.app.Activity;
import android.car.Car;
import android.car.CarNotConnectedException;
@@ -25,29 +24,21 @@
import android.car.drivingstate.CarUxRestrictions;
import android.car.drivingstate.CarUxRestrictionsManager;
import android.content.ComponentName;
+import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
+import android.view.View;
import android.widget.Button;
import android.widget.TextView;
-import androidx.car.widget.ListItem;
-import androidx.car.widget.ListItemAdapter;
-import androidx.car.widget.ListItemProvider;
-import androidx.car.widget.PagedListView;
-import androidx.car.widget.TextListItem;
-
-import java.util.ArrayList;
-import java.util.List;
-
/**
* Sample app that uses components in car support library to demonstrate Car drivingstate UXR
* status.
*/
public class MainActivity extends Activity {
public static final String TAG = "drivingstate";
-
private Car mCar;
private CarDrivingStateManager mCarDrivingStateManager;
private CarUxRestrictionsManager mCarUxRestrictionsManager;
@@ -56,8 +47,9 @@
private TextView mDistractionOptStatus;
private TextView mUxrStatus;
private Button mToggleButton;
+ private Button mSampleMsgButton;
+
private boolean mEnableUxR;
- private PagedListView mPagedListView;
private final ServiceConnection mCarConnectionListener =
new ServiceConnection() {
@@ -163,68 +155,24 @@
mDistractionOptStatus = findViewById(R.id.do_status);
mUxrStatus = findViewById(R.id.uxr_status);
mToggleButton = findViewById(R.id.toggle_status);
- mPagedListView = findViewById(R.id.paged_list_view);
-
- setUpPagedListView();
mToggleButton.setOnClickListener(v -> {
updateToggleUxREnable();
});
+ mSampleMsgButton = findViewById(R.id.launch_message);
+ mSampleMsgButton.setOnClickListener(this::launchSampleMsgActivity);
+
// Connect to car service
mCar = Car.createCar(this, mCarConnectionListener);
mCar.connect();
}
- private void setUpPagedListView() {
- ListItemAdapter adapter = new ListItemAdapter(this, populateData());
- mPagedListView.setAdapter(adapter);
+ private void launchSampleMsgActivity(View view) {
+ Intent msgIntent = new Intent(this, SampleMessageActivity.class);
+ startActivity(msgIntent);
}
- private ListItemProvider populateData() {
- List<ListItem> items = new ArrayList<>();
- items.add(createMessage(android.R.drawable.ic_menu_myplaces, "alice",
- "i have a really important message but it may hinder your ability to drive. "));
-
- items.add(createMessage(android.R.drawable.ic_menu_myplaces, "bob",
- "hey this is a really long message that i have always wanted to say. but before " +
- "saying it i feel it's only appropriate if i lay some groundwork for it. "
- + ""));
- items.add(createMessage(android.R.drawable.ic_menu_myplaces, "mom",
- "i think you are the best. i think you are the best. i think you are the best. " +
- "i think you are the best. i think you are the best. i think you are the "
- + "best. "
- +
- "i think you are the best. i think you are the best. i think you are the "
- + "best. "
- +
- "i think you are the best. i think you are the best. i think you are the "
- + "best. "
- +
- "i think you are the best. i think you are the best. i think you are the "
- + "best. "
- +
- "i think you are the best. i think you are the best. "));
- items.add(createMessage(android.R.drawable.ic_menu_myplaces, "john", "hello world"));
- items.add(createMessage(android.R.drawable.ic_menu_myplaces, "jeremy",
- "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor " +
- "incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, " +
- "quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo " +
- "consequat. Duis aute irure dolor in reprehenderit in voluptate velit " +
- "esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat " +
- "cupidatat non proident, sunt in culpa qui officia deserunt mollit " +
- "anim id est laborum."));
- return new ListItemProvider.ListProvider(items);
- }
-
- private TextListItem createMessage(@DrawableRes int profile, String contact, String message) {
- TextListItem item = new TextListItem(this);
- item.setPrimaryActionIcon(profile, false /* useLargeIcon */);
- item.setTitle(contact);
- item.setBody(message);
- item.setSupplementalIcon(android.R.drawable.stat_notify_chat, false);
- return item;
- }
@Override
protected void onDestroy() {
diff --git a/tests/UxRestrictionsSample/src/com/google/android/car/uxr/sample/SampleMessageActivity.java b/tests/UxRestrictionsSample/src/com/google/android/car/uxr/sample/SampleMessageActivity.java
new file mode 100644
index 0000000..1c9bc95
--- /dev/null
+++ b/tests/UxRestrictionsSample/src/com/google/android/car/uxr/sample/SampleMessageActivity.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2018 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.uxr.sample;
+
+import android.annotation.DrawableRes;
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.Button;
+
+import androidx.car.widget.ListItem;
+import androidx.car.widget.ListItemAdapter;
+import androidx.car.widget.ListItemProvider;
+import androidx.car.widget.PagedListView;
+import androidx.car.widget.TextListItem;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A Sample Messaging Activity that illustrates how to truncate the string length on receiving the
+ * corresponding UX restriction.
+ */
+public class SampleMessageActivity extends Activity {
+ private Button mHomeButton;
+ private PagedListView mPagedListView;
+ private ListItemAdapter mAdapter;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_sample_message);
+ mHomeButton = findViewById(R.id.home_button);
+ mHomeButton.setOnClickListener(this::returnHome);
+
+ mPagedListView = findViewById(R.id.paged_list_view);
+ setUpPagedListView();
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ if (mAdapter != null) {
+ mAdapter.start();
+ }
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ if (mAdapter != null) {
+ mAdapter.stop();
+ }
+ }
+
+ private void returnHome(View view) {
+ Intent homeIntent = new Intent(this, MainActivity.class);
+ startActivity(homeIntent);
+ }
+
+ private void setUpPagedListView() {
+ mAdapter = new ListItemAdapter(this, populateData());
+ mPagedListView.setAdapter(mAdapter);
+ }
+
+ private ListItemProvider populateData() {
+ List<ListItem> items = new ArrayList<>();
+ items.add(createMessage(android.R.drawable.ic_menu_myplaces, "alice",
+ "i have a really important message but it may hinder your ability to drive. "));
+
+ items.add(createMessage(android.R.drawable.ic_menu_myplaces, "bob",
+ "hey this is a really long message that i have always wanted to say. but before "
+ + "saying it i feel it's only appropriate if i lay some groundwork for it. "
+ + ""));
+ items.add(createMessage(android.R.drawable.ic_menu_myplaces, "mom",
+ "i think you are the best. i think you are the best. i think you are the best. "
+ + "i think you are the best. i think you are the best. i think you are the "
+ + "best. "
+ + "i think you are the best. i think you are the best. i think you are the "
+ + "best. "
+ + "i think you are the best. i think you are the best. i think you are the "
+ + "best. "
+ + "i think you are the best. i think you are the best. i think you are the "
+ + "best. "
+ + "i think you are the best. i think you are the best. "));
+ items.add(createMessage(android.R.drawable.ic_menu_myplaces, "john", "hello world"));
+ items.add(createMessage(android.R.drawable.ic_menu_myplaces, "jeremy",
+ "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor "
+ + "incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, "
+ + "quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo "
+ + "consequat. Duis aute irure dolor in reprehenderit in voluptate velit "
+ + "esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat "
+ + "cupidatat non proident, sunt in culpa qui officia deserunt mollit "
+ + "anim id est laborum."));
+ return new ListItemProvider.ListProvider(items);
+ }
+
+ private TextListItem createMessage(@DrawableRes int profile, String contact, String message) {
+ TextListItem item = new TextListItem(this);
+ item.setPrimaryActionIcon(profile, TextListItem.PRIMARY_ACTION_ICON_SIZE_SMALL);
+ item.setTitle(contact);
+ item.setBody(message);
+ item.setSupplementalIcon(android.R.drawable.stat_notify_chat, false);
+ return item;
+ }
+
+}
diff --git a/tests/VmsSubscriberClientSample/Android.mk b/tests/VmsSubscriberClientSample/Android.mk
index c577aaf..2568ffc 100644
--- a/tests/VmsSubscriberClientSample/Android.mk
+++ b/tests/VmsSubscriberClientSample/Android.mk
@@ -35,6 +35,4 @@
LOCAL_JAVA_LIBRARIES += android.car
-include packages/services/Car/car-support-lib/car-support.mk
-
include $(BUILD_PACKAGE)
\ No newline at end of file
diff --git a/tests/VmsSubscriberClientSample/src/com/google/android/car/vms/subscriber/VmsSubscriberClientSampleActivity.java b/tests/VmsSubscriberClientSample/src/com/google/android/car/vms/subscriber/VmsSubscriberClientSampleActivity.java
index a82350b..41de024 100644
--- a/tests/VmsSubscriberClientSample/src/com/google/android/car/vms/subscriber/VmsSubscriberClientSampleActivity.java
+++ b/tests/VmsSubscriberClientSample/src/com/google/android/car/vms/subscriber/VmsSubscriberClientSampleActivity.java
@@ -17,15 +17,19 @@
package com.google.android.car.vms.subscriber;
import android.app.Activity;
+import android.car.Car;
+import android.car.CarNotConnectedException;
import android.car.vms.VmsAvailableLayers;
import android.car.vms.VmsLayer;
import android.car.vms.VmsSubscriberManager;
+import android.content.ComponentName;
+import android.content.ServiceConnection;
import android.content.pm.PackageManager;
import android.os.Bundle;
-import android.support.car.Car;
-import android.support.car.CarConnectionCallback;
+import android.os.IBinder;
import android.util.Log;
import android.widget.TextView;
+
import java.util.concurrent.Executor;
/**
@@ -57,7 +61,7 @@
setContentView(R.layout.activity_main);
mTextView = (TextView) findViewById(R.id.textview);
if (getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) {
- mCarApi = Car.createCar(this, mCarConnectionCallback);
+ mCarApi = Car.createCar(this, mCarServiceConnection);
mCarApi.connect();
} else {
Log.d(TAG, "No automotive feature.");
@@ -73,24 +77,24 @@
Log.i(TAG, "onDestroy");
}
- private final CarConnectionCallback mCarConnectionCallback = new CarConnectionCallback() {
+ private final ServiceConnection mCarServiceConnection = new ServiceConnection() {
@Override
- public void onConnected(Car car) {
+ public void onServiceConnected(ComponentName name, IBinder service) {
Log.d(TAG, "Connected to Car Service");
mVmsSubscriberManager = getVmsSubscriberManager();
configureSubscriptions(mVmsSubscriberManager);
}
@Override
- public void onDisconnected(Car car) {
+ public void onServiceDisconnected(ComponentName name) {
Log.d(TAG, "Disconnect from Car Service");
}
private VmsSubscriberManager getVmsSubscriberManager() {
try {
return (VmsSubscriberManager) mCarApi.getCarManager(
- android.car.Car.VMS_SUBSCRIBER_SERVICE);
- } catch (android.support.car.CarNotConnectedException e) {
+ Car.VMS_SUBSCRIBER_SERVICE);
+ } catch (CarNotConnectedException e) {
Log.e(TAG, "Car is not connected!", e);
}
return null;
@@ -100,7 +104,7 @@
try {
vmsSubscriberManager.setVmsSubscriberClientCallback(mExecutor, mClientCallback);
vmsSubscriberManager.subscribe(TEST_LAYER);
- } catch (android.car.CarNotConnectedException e) {
+ } catch (CarNotConnectedException e) {
Log.e(TAG, "Car is not connected!", e);
}
}
diff --git a/tests/android_car_api_test/src/android/car/apitest/CarHvacManagerTest.java b/tests/android_car_api_test/src/android/car/apitest/CarHvacManagerTest.java
index 7196d14..2fc57eb 100644
--- a/tests/android_car_api_test/src/android/car/apitest/CarHvacManagerTest.java
+++ b/tests/android_car_api_test/src/android/car/apitest/CarHvacManagerTest.java
@@ -43,7 +43,7 @@
public void testAllHvacProperties() throws Exception {
List<CarPropertyConfig> properties = mHvacManager.getPropertyList();
Set<Class> supportedTypes = new HashSet<>(Arrays.asList(
- new Class[] { Integer.class, Float.class, Boolean.class }));
+ new Class[] { Integer.class, Float.class, Boolean.class, Integer[].class }));
for (CarPropertyConfig property : properties) {
if (supportedTypes.contains(property.getPropertyType())) {
@@ -80,7 +80,6 @@
break;
case CarHvacManager.ID_ZONED_FAN_SPEED_SETPOINT: // zoned int
case CarHvacManager.ID_ZONED_FAN_SPEED_RPM:
- case CarHvacManager.ID_ZONED_FAN_DIRECTION_AVAILABLE:
case CarHvacManager.ID_ZONED_SEAT_TEMP:
checkTypeAndGlobal(Integer.class, false, property);
checkIntMinMax(property);
@@ -88,6 +87,9 @@
case CarHvacManager.ID_ZONED_FAN_DIRECTION:
checkTypeAndGlobal(Integer.class, false, property);
break;
+ case CarHvacManager.ID_ZONED_FAN_DIRECTION_AVAILABLE:
+ checkTypeAndGlobal(Integer[].class, false, property);
+ break;
case CarHvacManager.ID_ZONED_AC_ON: // zoned boolean
case CarHvacManager.ID_ZONED_AUTOMATIC_MODE_ON:
case CarHvacManager.ID_ZONED_AIR_RECIRCULATION_ON:
@@ -103,10 +105,10 @@
private void checkTypeAndGlobal(Class clazz, boolean global, CarPropertyConfig<Integer> property) {
assertEquals("Wrong type, expecting " + clazz + " type for id:" + property.getPropertyId(),
- clazz, property.getPropertyType());
+ clazz, property.getPropertyType());
assertEquals("Wrong zone, should " + (global ? "" : "not ") + "be global for id: " +
- property.getPropertyId() + ", area type:" + property.getAreaType(),
- global, property.isGlobalProperty());
+ property.getPropertyId() + ", area type:" + property.getAreaType(),
+ global, property.isGlobalProperty());
}
private void checkIntMinMax(CarPropertyConfig<Integer> property) {
diff --git a/tests/carservice_test/src/com/android/car/CarPackageManagerTest.java b/tests/carservice_test/src/com/android/car/CarPackageManagerTest.java
index 9c65555..84afde9 100644
--- a/tests/carservice_test/src/com/android/car/CarPackageManagerTest.java
+++ b/tests/carservice_test/src/com/android/car/CarPackageManagerTest.java
@@ -25,6 +25,7 @@
import android.car.content.pm.CarAppBlockingPolicy;
import android.car.content.pm.CarPackageManager;
import android.support.test.filters.SmallTest;
+import android.support.test.filters.Suppress;
import android.support.test.runner.AndroidJUnit4;
import android.util.Log;
@@ -82,6 +83,9 @@
assertFalse(mCarPm.isServiceDistractionOptimized(serviceClassName, null));
}
+ // TODO(b/113531788): Suppress this temporarily. Need to find the cause of issue and re-evaluate
+ // if the test is necessary.
+ @Suppress
@Test
public void testSettingWhitelist() throws Exception {
init(false);
diff --git a/tests/carservice_test/src/com/android/car/VmsHalServiceSubscriptionEventTest.java b/tests/carservice_test/src/com/android/car/VmsHalServiceSubscriptionEventTest.java
index 82c9361..16b0572 100644
--- a/tests/carservice_test/src/com/android/car/VmsHalServiceSubscriptionEventTest.java
+++ b/tests/carservice_test/src/com/android/car/VmsHalServiceSubscriptionEventTest.java
@@ -25,6 +25,8 @@
import android.hardware.automotive.vehicle.V2_0.VehicleProperty;
import android.hardware.automotive.vehicle.V2_0.VehiclePropertyAccess;
import android.hardware.automotive.vehicle.V2_0.VehiclePropertyChangeMode;
+import android.hardware.automotive.vehicle.V2_0.VmsAvailabilityStateIntegerValuesIndex;
+import android.hardware.automotive.vehicle.V2_0.VmsBaseMessageIntegerValuesIndex;
import android.hardware.automotive.vehicle.V2_0.VmsMessageType;
import android.hardware.automotive.vehicle.V2_0.VmsMessageWithLayerIntegerValuesIndex;
import android.hardware.automotive.vehicle.V2_0.VmsSubscriptionsStateIntegerValuesIndex;
@@ -66,9 +68,9 @@
@Override
public void setUp() throws Exception {
+ mHalHandlerSemaphore = new Semaphore(0);
super.setUp();
mHal = getMockedVehicleHal();
- mHalHandlerSemaphore = new Semaphore(0);
}
@Test
@@ -99,19 +101,30 @@
* responds with the same layers.
*/
private void subscriptionTestLogic(List<VmsLayer> layers) throws Exception {
+ // Wait for availability change message that signals the service is ready.
+ assertTrue(mHalHandlerSemaphore.tryAcquire(2L, TimeUnit.SECONDS));
+ // Validate response.
+ ArrayList<Integer> v = mHalHandler.getValues();
+ int messageType = v.get(VmsBaseMessageIntegerValuesIndex.MESSAGE_TYPE);
+ int sequenceNumber = v.get(VmsAvailabilityStateIntegerValuesIndex.SEQUENCE_NUMBER);
+ assertEquals(VmsMessageType.AVAILABILITY_CHANGE, messageType);
+ assertEquals(0, sequenceNumber);
+
for (VmsLayer layer : layers) {
subscribeViaHal(layer);
}
// Send subscription request.
mHal.injectEvent(createHalSubscriptionRequest());
- // Wait for response.
+
+ // Wait for subscription response
assertTrue(mHalHandlerSemaphore.tryAcquire(2L, TimeUnit.SECONDS));
+
// Validate response.
- ArrayList<Integer> v = mHalHandler.getValues();
- int messageType = v.get(VmsSubscriptionsStateIntegerValuesIndex.MESSAGE_TYPE);
- int sequenceNumber = v.get(VmsSubscriptionsStateIntegerValuesIndex.SEQUENCE_NUMBER);
- int numberLayers = v.get(VmsSubscriptionsStateIntegerValuesIndex.NUMBER_OF_LAYERS);
+ v = mHalHandler.getValues();
+ messageType = v.get(VmsBaseMessageIntegerValuesIndex.MESSAGE_TYPE);
assertEquals(VmsMessageType.SUBSCRIPTIONS_RESPONSE, messageType);
+ sequenceNumber = v.get(VmsSubscriptionsStateIntegerValuesIndex.SEQUENCE_NUMBER);
+ int numberLayers = v.get(VmsSubscriptionsStateIntegerValuesIndex.NUMBER_OF_LAYERS);
assertEquals(layers.size(), numberLayers);
List<VmsLayer> receivedLayers = new ArrayList<>();
int start = VmsSubscriptionsStateIntegerValuesIndex.SUBSCRIPTIONS_START;
@@ -136,11 +149,11 @@
assertTrue(mHalHandlerSemaphore.tryAcquire(2L, TimeUnit.SECONDS));
// Validate response.
ArrayList<Integer> v = mHalHandler.getValues();
- int messsageType = v.get(VmsMessageWithLayerIntegerValuesIndex.MESSAGE_TYPE);
+ int messsageType = v.get(VmsBaseMessageIntegerValuesIndex.MESSAGE_TYPE);
+ assertEquals(VmsMessageType.SUBSCRIBE, messsageType);
int layerId = v.get(VmsMessageWithLayerIntegerValuesIndex.LAYER_TYPE);
int layerVersion = v.get(VmsMessageWithLayerIntegerValuesIndex.LAYER_VERSION);
int fused = v.get(VmsMessageWithLayerIntegerValuesIndex.LAYER_SUBTYPE);
- assertEquals(VmsMessageType.SUBSCRIBE, messsageType);
assertEquals(layer.getType(), layerId);
assertEquals(layer.getVersion(), layerVersion);
}
@@ -173,4 +186,4 @@
return mValues;
}
}
-}
\ No newline at end of file
+}
diff --git a/tests/carservice_test/src/com/android/car/VmsSubscriberManagerTest.java b/tests/carservice_test/src/com/android/car/VmsSubscriberManagerTest.java
index 643ffff..63b0e62 100644
--- a/tests/carservice_test/src/com/android/car/VmsSubscriberManagerTest.java
+++ b/tests/carservice_test/src/com/android/car/VmsSubscriberManagerTest.java
@@ -119,9 +119,9 @@
@Override
public void setUp() throws Exception {
mExecutor = new ThreadPerTaskExecutor();
- super.setUp();
mSubscriberSemaphore = new Semaphore(0);
mHalHandlerSemaphore = new Semaphore(0);
+ super.setUp();
}
// Test injecting a value in the HAL and verifying it propagates to a subscriber.
diff --git a/tests/carservice_test/src/com/android/car/garagemode/ControllerTest.java b/tests/carservice_test/src/com/android/car/garagemode/ControllerTest.java
new file mode 100644
index 0000000..d724161
--- /dev/null
+++ b/tests/carservice_test/src/com/android/car/garagemode/ControllerTest.java
@@ -0,0 +1,195 @@
+/*
+ * Copyright (C) 2018 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.garagemode;
+
+import static com.android.car.garagemode.GarageMode.ACTION_GARAGE_MODE_OFF;
+import static com.android.car.garagemode.GarageMode.ACTION_GARAGE_MODE_ON;
+import static com.android.car.garagemode.GarageMode.JOB_SNAPSHOT_INITIAL_UPDATE_MS;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import android.car.Car;
+import android.car.CarNotConnectedException;
+import android.car.hardware.power.CarPowerManager;
+import android.car.hardware.power.CarPowerManager.CarPowerStateListener;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Handler;
+import android.os.Looper;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class ControllerTest {
+ private static final Logger LOG = new Logger("ControllerTest");
+
+ @Mock private Context mContextMock;
+ @Mock private Looper mLooperMock;
+ @Mock private Handler mHandlerMock;
+ @Mock private Car mCarMock;
+ @Mock private CarPowerManager mCarPowerManagerMock;
+ @Captor private ArgumentCaptor<Intent> mIntentCaptor;
+ @Captor private ArgumentCaptor<Integer> mIntegerCaptor;
+
+ private static final String[] sTemplateWakeupSchedule = new String[] {
+ "15m,1",
+ "6h,4",
+ "1d,1"};
+ private static final int[] sTemplateWakeupScheduleSeconds = new int[] {
+ 15 * 60,
+ 6 * 60 * 60,
+ 6 * 60 * 60,
+ 6 * 60 * 60,
+ 6 * 60 * 60,
+ 24 * 60 * 60};
+ private Controller mController;
+ private WakeupPolicy mWakeupPolicy;
+ private CompletableFuture<Void> mFuture;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mWakeupPolicy = new WakeupPolicy(sTemplateWakeupSchedule);
+ mController = new Controller(
+ mContextMock,
+ mLooperMock,
+ mWakeupPolicy,
+ mHandlerMock,
+ null,
+ mCarMock);
+ mController.setCarPowerManager(mCarPowerManagerMock);
+ mFuture = new CompletableFuture<>();
+ }
+
+ @Test
+ public void testOnSuspendEnter_shouldInitiateGarageMode() {
+ startAndAssertGarageModeWithSignal(CarPowerStateListener.SUSPEND_ENTER);
+ verify(mContextMock).sendBroadcast(mIntentCaptor.capture());
+ verifyGarageModeBroadcast(mIntentCaptor.getAllValues(), 1, ACTION_GARAGE_MODE_ON);
+ }
+
+ @Test
+ public void testOnShutdownEnter_shouldInitiateGarageMode() {
+ startAndAssertGarageModeWithSignal(CarPowerStateListener.SHUTDOWN_ENTER);
+ verify(mContextMock).sendBroadcast(mIntentCaptor.capture());
+ verifyGarageModeBroadcast(mIntentCaptor.getAllValues(), 1, ACTION_GARAGE_MODE_ON);
+ }
+
+ @Test
+ public void testOnShutdownCancelled_shouldCancelGarageMode() {
+ startAndAssertGarageModeWithSignal(CarPowerStateListener.SUSPEND_ENTER);
+
+ // Sending shutdown cancelled signal to controller, GarageMode should wrap up and stop
+ mController.onStateChanged(CarPowerStateListener.SHUTDOWN_CANCELLED, null);
+
+ // Verify that wake up counter is reset and GarageMode is not active anymore
+ assertThat(mController.mWakeupPolicy.mIndex).isEqualTo(0);
+ assertThat(mController.isGarageModeActive()).isFalse();
+
+ // Verify that monitoring thread has stopped
+ verify(mHandlerMock).removeCallbacks(any(Runnable.class));
+
+ // Verify that OFF signal broadcasted to JobScheduler
+ verify(mContextMock, times(2)).sendBroadcast(mIntentCaptor.capture());
+ verifyGarageModeBroadcast(mIntentCaptor.getAllValues(), 1, ACTION_GARAGE_MODE_ON);
+ verifyGarageModeBroadcast(mIntentCaptor.getAllValues(), 2, ACTION_GARAGE_MODE_OFF);
+
+ // Verify that bounded future got cancelled
+ assertThat(mFuture.isDone()).isTrue();
+ assertThat(mFuture.isCancelled()).isTrue();
+ }
+
+ @Test
+ public void testWakeupTimeProgression() throws CarNotConnectedException {
+ // Doing initial suspend
+ startAndAssertGarageModeWithSignal(CarPowerStateListener.SUSPEND_ENTER);
+
+ // Finish GarageMode and check next scheduled time
+ mController.finishGarageMode();
+ assertThat(mController.isGarageModeActive()).isFalse();
+
+ // Start GarageMode again without waking up car
+ mFuture = new CompletableFuture<>();
+ mController.onStateChanged(CarPowerStateListener.SUSPEND_ENTER, mFuture);
+
+ assertThat(mController.mWakeupPolicy.mIndex).isEqualTo(2);
+ assertThat(mController.isGarageModeActive()).isTrue();
+
+ // Finish GarageMode and check next scheduled time
+ mController.finishGarageMode();
+ assertThat(mController.isGarageModeActive()).isFalse();
+
+ for (int i = 0; i < 4; i++) {
+ mFuture = new CompletableFuture<>();
+ mController.onStateChanged(CarPowerStateListener.SUSPEND_ENTER, mFuture);
+ mController.finishGarageMode();
+ assertThat(mController.isGarageModeActive()).isFalse();
+ assertThat(mController.mWakeupPolicy.mIndex).isEqualTo(i + 3);
+ }
+ verify(mCarPowerManagerMock, times(6)).scheduleNextWakeupTime(mIntegerCaptor.capture());
+ verifyScheduledTimes(mIntegerCaptor.getAllValues());
+ }
+
+ private void verifyGarageModeBroadcast(List<Intent> intents, int times, String action) {
+ // Capture sent intent and verify that it is correct
+ Intent i = intents.get(times - 1);
+ assertThat(i.getAction()).isEqualTo(action);
+
+ // Verify that additional critical flags are bundled as well
+ final int flags = Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_NO_ABORT;
+ boolean areRequiredFlagsSet = ((flags & i.getFlags()) == flags);
+ assertThat(areRequiredFlagsSet).isTrue();
+ }
+
+ private void verifyScheduledTimes(List<Integer> ints) {
+ int idx = 0;
+ for (int i : ints) {
+ assertThat(i).isEqualTo(sTemplateWakeupScheduleSeconds[idx++]);
+ }
+ }
+
+ private void startAndAssertGarageModeWithSignal(int signal) {
+ assertThat(mController.mWakeupPolicy.mIndex).isEqualTo(0);
+
+ // Sending notification that state has changed
+ mController.onStateChanged(signal, mFuture);
+
+ // Assert that GarageMode has been started
+ assertThat(mController.isGarageModeActive()).isTrue();
+ assertThat(mController.mWakeupPolicy.mIndex).isEqualTo(1);
+
+ // Verify that worker that polls running jobs from JobScheduler is scheduled.
+ verify(mHandlerMock).postDelayed(any(), eq(JOB_SNAPSHOT_INITIAL_UPDATE_MS));
+ }
+}
diff --git a/tests/carservice_test/src/com/android/car/garagemode/GarageModeServiceTest.java b/tests/carservice_test/src/com/android/car/garagemode/GarageModeServiceTest.java
index 8a9a90d..b67c50d 100644
--- a/tests/carservice_test/src/com/android/car/garagemode/GarageModeServiceTest.java
+++ b/tests/carservice_test/src/com/android/car/garagemode/GarageModeServiceTest.java
@@ -16,286 +16,52 @@
package com.android.car.garagemode;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
+import static com.google.common.truth.Truth.assertThat;
-import android.car.settings.CarSettings;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.ContentResolver;
import android.content.Context;
-import android.content.SharedPreferences;
-import android.os.HandlerThread;
-import android.os.Looper;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.annotation.UiThreadTest;
-import android.support.test.filters.MediumTest;
+import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
-import com.android.car.CarPowerManagementService;
-import com.android.car.DeviceIdleControllerWrapper;
-import com.android.car.R;
-
+import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import java.io.PrintWriter;
import java.util.List;
@RunWith(AndroidJUnit4.class)
-@MediumTest
+@SmallTest
public class GarageModeServiceTest {
- private static final int WAIT_FOR_COMPLETION_TIME_MS = 3000;
+ @Mock private Context mMockContext;
+ @Mock private Controller mMockController;
+ @Mock private ContentResolver mMockContentResolver;
+ @Mock private PrintWriter mMockPrintWriter;
+ @Captor private ArgumentCaptor<String> mCaptorString;
- @Test
- @UiThreadTest
- public void testMaintenanceActive() throws Exception {
- MockCarPowerManagementService powerManagementService = new MockCarPowerManagementService();
- MockDeviceIdleController controller = new MockDeviceIdleController(true);
- GarageModeServiceForTest garageMode = new GarageModeServiceForTest(getContext(),
- powerManagementService,
- controller);
- garageMode.init();
- final int index1 = garageMode.getGarageModeIndex();
- assertEquals(garageMode.getMaintenanceWindow(),
- powerManagementService.doNotifyPrepareShutdown(false));
- assertEquals(true, garageMode.isInGarageMode());
- assertEquals(true, garageMode.isMaintenanceActive());
+ private GarageModeService mService;
- controller.setMaintenanceActivity(false);
- assertEquals(false, garageMode.isInGarageMode());
- assertEquals(false, garageMode.isMaintenanceActive());
- final int index2 = garageMode.getGarageModeIndex();
-
- assertEquals(1, index2 - index1);
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ when(mMockContext.getContentResolver()).thenReturn(mMockContentResolver);
+ mService = new GarageModeService(mMockContext, mMockController);
}
@Test
- @UiThreadTest
- public void testMaintenanceInactive() throws Exception {
- MockCarPowerManagementService powerManagementService = new MockCarPowerManagementService();
- MockDeviceIdleController controller = new MockDeviceIdleController(false);
- GarageModeServiceForTest garageMode = new GarageModeServiceForTest(getContext(),
- powerManagementService,
- controller);
- garageMode.init();
- assertEquals(garageMode.getMaintenanceWindow(),
- powerManagementService.doNotifyPrepareShutdown(false));
- assertEquals(true, garageMode.isInGarageMode());
- assertEquals(false, garageMode.isMaintenanceActive());
- }
+ public void testDump_shouldSucceed() {
+ when(mMockController.isGarageModeActive()).thenReturn(true);
- @Test
- @UiThreadTest
- public void testDisplayOn() throws Exception {
- MockCarPowerManagementService powerManagementService = new MockCarPowerManagementService();
- MockDeviceIdleController controller = new MockDeviceIdleController(true);
- GarageModeServiceForTest garageMode = new GarageModeServiceForTest(getContext(),
- powerManagementService,
- controller);
- garageMode.init();
-
- powerManagementService.doNotifyPrepareShutdown(false);
- assertTrue(garageMode.getGarageModeIndex() > 0);
- powerManagementService.doNotifyPowerOn(true);
- assertEquals(0, garageMode.getGarageModeIndex());
- }
-
- @Test
- @UiThreadTest
- public void testPolicyIndexing() throws Exception {
- // Background processing of asynchronous messages.
- HandlerThread thread = new HandlerThread("testPolicy");
- thread.start();
-
- // Test that the index is saved in the prefs and that this index is used to determine the
- // next wakeup time.
- MockCarPowerManagementService powerManagementService = new MockCarPowerManagementService();
- MockDeviceIdleController controller = new MockDeviceIdleController(true);
- GarageModeServiceForTest garageMode = new GarageModeServiceForTest(getContext(),
- powerManagementService,
- controller,
- thread.getLooper());
- GarageModePolicy policy = new GarageModePolicy(new String[] {
- "15m,1",
- "6h,8",
- "1d,5",
- });
- SharedPreferences prefs =
- getContext().getSharedPreferences("testPolicy", Context.MODE_PRIVATE);
- prefs.edit().putInt("garage_mode_index", 0).apply();
- garageMode.init(policy, prefs);
-
- assertEquals(15 * 60, garageMode.getWakeupTime());
- garageMode.onPrepareShutdown(false);
- garageMode.onShutdown();
- assertEquals(6 * 60 * 60, garageMode.getWakeupTime());
- Thread.sleep(WAIT_FOR_COMPLETION_TIME_MS);
- assertEquals(1, prefs.getInt("garage_mode_index", 0));
-
- garageMode = new GarageModeServiceForTest(getContext(),
- powerManagementService,
- controller,
- thread.getLooper());
- // Jump ahead 8 restarts.
- prefs = getContext().getSharedPreferences("testPolicy", Context.MODE_PRIVATE);
- prefs.edit().putInt("garage_mode_index", 8).apply();
- garageMode.init(policy, prefs);
-
- assertEquals(6 * 60 * 60, garageMode.getWakeupTime());
- garageMode.onPrepareShutdown(false);
- garageMode.onShutdown();
- assertEquals(24 * 60 * 60, garageMode.getWakeupTime());
- Thread.sleep(WAIT_FOR_COMPLETION_TIME_MS);
- assertEquals(9, prefs.getInt("garage_mode_index", 0));
- }
-
- @Test
- public void testPolicyParserValid() throws Exception {
- WakeupInterval[] expected = new WakeupInterval[] {
- new WakeupInterval(15 * 60, 1),
- new WakeupInterval(6 * 60 * 60, 8),
- new WakeupInterval(24 * 60 * 60, 5),
- };
- List<WakeupInterval> received = new GarageModePolicy(new String[] {
- "15m,1",
- "6h,8",
- "1d,5",
- }).getWakeupIntervals();
-
- assertEquals(expected.length, received.size());
- for (int i = 0; i < expected.length; i++) {
- assertEquals(expected[i].getWakeupInterval(), received.get(i).getWakeupInterval());
- assertEquals(expected[i].getNumAttempts(), received.get(i).getNumAttempts());
- }
- }
-
- @Test
- public void testPolicyParser() {
- GarageModePolicy policy;
-
- policy = new GarageModePolicy(null);
- assertEquals(0, policy.getWakeupIntervals().size());
-
- policy = new GarageModePolicy(new String[] {});
- assertEquals(0, policy.getWakeupIntervals().size());
-
- policy = new GarageModePolicy(new String[] {""});
- assertEquals(0, policy.getWakeupIntervals().size());
-
- policy = new GarageModePolicy(new String[] {"15,1"});
- assertEquals(0, policy.getWakeupIntervals().size());
-
- policy = new GarageModePolicy(new String[] {"15y,1"});
- assertEquals(0, policy.getWakeupIntervals().size());
-
- policy = new GarageModePolicy(new String[] {"15m"});
- assertEquals(0, policy.getWakeupIntervals().size());
-
- policy = new GarageModePolicy(new String[] {"15m,Q"});
- assertEquals(0, policy.getWakeupIntervals().size());
-
- policy = new GarageModePolicy(new String[] {"15m,-1"});
- assertEquals(0, policy.getWakeupIntervals().size());
-
- policy = new GarageModePolicy(new String[] {",1"});
- assertEquals(0, policy.getWakeupIntervals().size());
-
- policy = new GarageModePolicy(new String[] {"m,1"});
- assertEquals(0, policy.getWakeupIntervals().size());
-
- policy = new GarageModePolicy(new String[] {"Qm,1"});
- assertEquals(0, policy.getWakeupIntervals().size());
-
- policy = new GarageModePolicy(new String[] {"-10m,1"});
- assertEquals(0, policy.getWakeupIntervals().size());
-
- }
-
- @Test
- public void testPolicyInResource() throws Exception {
- // Test that the policy in the resource file parses fine.
- GarageModePolicy policy = new GarageModePolicy(getContext().getResources().getStringArray(
- R.array.config_garageModeCadence));
- assertTrue(policy.getWakeupIntervals().size() > 0);
- }
-
- private static class MockCarPowerManagementService extends CarPowerManagementService {
- public long doNotifyPrepareShutdown(boolean shuttingdown) {
- return notifyPrepareShutdown(shuttingdown);
- }
-
- public void doNotifyPowerOn(boolean displayOn) {
- notifyPowerOn(displayOn);
- }
- }
-
- private static class GarageModeServiceForTest extends GarageModeService {
- GarageModeServiceForTest(Context context,
- CarPowerManagementService powerManagementService,
- DeviceIdleControllerWrapper controllerWrapper,
- Looper looper) {
- super(context, powerManagementService, controllerWrapper, looper);
- }
-
- GarageModeServiceForTest(Context context,
- CarPowerManagementService powerManagementService,
- DeviceIdleControllerWrapper controllerWrapper) {
- super(context, powerManagementService, controllerWrapper, Looper.myLooper());
- }
-
- public long getMaintenanceWindow() {
- return CarSettings.DEFAULT_GARAGE_MODE_MAINTENANCE_WINDOW;
- }
-
- public boolean isInGarageMode() {
- synchronized (this) {
- return mInGarageMode;
- }
- }
-
- public boolean isMaintenanceActive() {
- synchronized (this) {
- return mMaintenanceActive;
- }
- }
-
- public int getGarageModeIndex() {
- synchronized (this) {
- return mGarageModeIndex;
- }
- }
- }
-
- private Context getContext() {
- return InstrumentationRegistry.getTargetContext();
- }
-
- private static class MockDeviceIdleController extends DeviceIdleControllerWrapper {
-
- private final boolean mInitialActive;
-
- MockDeviceIdleController(boolean active) {
- super();
- mInitialActive = active;
- }
-
- @Override
- protected boolean startLocked() {
- return mInitialActive;
- }
-
- @Override
- public void stopTracking() {
- // nothing to clean up
- }
-
- @Override
- protected void reportActiveLocked(final boolean active) {
- // directly calling the callback instead of posting to handler, to make testing easier.
- if (mListener.get() != null) {
- mListener.get().onMaintenanceActivityChanged(active);
- }
- }
-
- public void setMaintenanceActivity(boolean active) {
- super.setMaintenanceActivity(active);
- }
+ mService.dump(mMockPrintWriter);
+ verify(mMockPrintWriter).println(mCaptorString.capture());
+ List<String> strings = mCaptorString.getAllValues();
+ assertThat(strings.get(0)).isEqualTo("GarageModeInProgress true");
}
}
diff --git a/tests/carservice_test/src/com/android/car/garagemode/WakeupPolicyTest.java b/tests/carservice_test/src/com/android/car/garagemode/WakeupPolicyTest.java
new file mode 100644
index 0000000..0a36754
--- /dev/null
+++ b/tests/carservice_test/src/com/android/car/garagemode/WakeupPolicyTest.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2018 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.garagemode;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import com.android.car.R;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class WakeupPolicyTest {
+ @Test
+ public void testPolicyParser() {
+ WakeupPolicy policy;
+
+ policy = new WakeupPolicy(null);
+ assertThat(policy.getWakupIntervalsAmount()).isEqualTo(0);
+
+ policy = new WakeupPolicy(new String[] {});
+ assertThat(policy.getWakupIntervalsAmount()).isEqualTo(0);
+
+ policy = new WakeupPolicy(new String[] {""});
+ assertThat(policy.getWakupIntervalsAmount()).isEqualTo(0);
+
+ policy = new WakeupPolicy(new String[] {"15,1"});
+ assertThat(policy.getWakupIntervalsAmount()).isEqualTo(0);
+
+ policy = new WakeupPolicy(new String[] {"15y,1"});
+ assertThat(policy.getWakupIntervalsAmount()).isEqualTo(0);
+
+ policy = new WakeupPolicy(new String[] {"15m"});
+ assertThat(policy.getWakupIntervalsAmount()).isEqualTo(0);
+
+ policy = new WakeupPolicy(new String[] {"15m,Q"});
+ assertThat(policy.getWakupIntervalsAmount()).isEqualTo(0);
+
+ policy = new WakeupPolicy(new String[] {"15m,-1"});
+ assertThat(policy.getWakupIntervalsAmount()).isEqualTo(0);
+
+ policy = new WakeupPolicy(new String[] {",1"});
+ assertThat(policy.getWakupIntervalsAmount()).isEqualTo(0);
+
+ policy = new WakeupPolicy(new String[] {"m,1"});
+ assertThat(policy.getWakupIntervalsAmount()).isEqualTo(0);
+
+ policy = new WakeupPolicy(new String[] {"Qm,1"});
+ assertThat(policy.getWakupIntervalsAmount()).isEqualTo(0);
+
+ policy = new WakeupPolicy(new String[] {"-10m,1"});
+ assertThat(policy.getWakupIntervalsAmount()).isEqualTo(0);
+ }
+
+ @Test
+ public void testPolicyInResource() throws Exception {
+ // Test that the policy in the resource file parses fine.
+ WakeupPolicy policy = new WakeupPolicy(
+ getContext().getResources().getStringArray(R.array.config_garageModeCadence));
+ assertThat(policy.getWakupIntervalsAmount() > 0).isTrue();
+ }
+
+ private Context getContext() {
+ return InstrumentationRegistry.getTargetContext();
+ }
+}
diff --git a/tests/carservice_unit_test/src/com/android/car/CarPowerManagementServiceTest.java b/tests/carservice_unit_test/src/com/android/car/CarPowerManagementServiceTest.java
index cb2b4b8..d20f570 100644
--- a/tests/carservice_unit_test/src/com/android/car/CarPowerManagementServiceTest.java
+++ b/tests/carservice_unit_test/src/com/android/car/CarPowerManagementServiceTest.java
@@ -94,7 +94,7 @@
}
public void testDisplayOff() throws Exception {
- initTest(0,0);
+ initTest(0, 0);
// it will call display on for initial state
assertTrue(mDisplayInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS));
mPowerHal.setCurrentPowerState(new PowerState(PowerHalService.STATE_ON_DISP_OFF, 0));
@@ -105,7 +105,7 @@
// start with display off
mSystemInterface.setDisplayState(false);
mDisplayInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS);
- initTest(0,0);
+ initTest(0, 0);
// display should be turned on as it started with off state.
assertTrue(mDisplayInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS));
@@ -116,9 +116,12 @@
initTest(0, wakeupTime);
assertTrue(mDisplayInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS));
- mPowerHal.setCurrentPowerState(new PowerState(PowerHalService.STATE_SHUTDOWN_PREPARE,
- PowerHalService.SHUTDOWN_IMMEDIATELY));
- assertStateReceived(PowerHalService.SET_SHUTDOWN_START, wakeupTime);
+ mPowerHal.setCurrentPowerState(
+ new PowerState(
+ PowerHalService.STATE_SHUTDOWN_PREPARE,
+ PowerHalService.SHUTDOWN_IMMEDIATELY));
+ // In case of immediate shutdown, no modules will schedule a next wake up
+ assertStateReceived(PowerHalService.SET_SHUTDOWN_START, 0);
assertFalse(mDisplayInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS));
mPowerEventListener.waitForShutdown(WAIT_TIMEOUT_MS);
mSystemStateInterface.waitForShutdown(WAIT_TIMEOUT_MS);
@@ -208,7 +211,8 @@
wakeupTimeReceived = mSystemStateInterface.waitForSleepEntryAndWakeup(WAIT_TIMEOUT_MS);
assertEquals(wakeupTime, wakeupTimeReceived);
assertStateReceived(PowerHalService.SET_DEEP_SLEEP_EXIT, 0);
- assertStateReceived(PowerHalService.SET_SHUTDOWN_START, wakeupTime);
+ // Since we just woke up from shutdown, wake up time will be 0
+ assertStateReceived(PowerHalService.SET_SHUTDOWN_START, 0);
mPowerEventListener.waitForShutdown(WAIT_TIMEOUT_MS);
mSystemStateInterface.waitForShutdown(WAIT_TIMEOUT_MS);
assertFalse(mDisplayInterface.getDisplayState());
@@ -411,6 +415,7 @@
public long onPrepareShutdown(boolean shuttingDown) {
mShuttingDown = shuttingDown;
mPrepareShutdownWait.release();
+ mService.scheduleNextWakeupTime(mWakeupTime);
return mProcessingTime;
}
public boolean waitForPrepareShutdown(long timeoutMs) throws Exception {
diff --git a/tests/carservice_unit_test/src/com/android/car/CarUserManagerHelperTest.java b/tests/carservice_unit_test/src/com/android/car/CarUserManagerHelperTest.java
index 7f53da5..fd913bc 100644
--- a/tests/carservice_unit_test/src/com/android/car/CarUserManagerHelperTest.java
+++ b/tests/carservice_unit_test/src/com/android/car/CarUserManagerHelperTest.java
@@ -486,6 +486,32 @@
}
@Test
+ public void testSwitchToId() {
+ int userIdToSwitchTo = mForegroundUserId + 2;
+ doReturn(true).when(mActivityManager).switchUser(userIdToSwitchTo);
+
+ assertThat(mCarUserManagerHelper.switchToUserId(userIdToSwitchTo)).isTrue();
+ verify(mActivityManager).switchUser(userIdToSwitchTo);
+ }
+
+ @Test
+ public void testSwitchToForegroundIdExitsEarly() {
+ doReturn(true).when(mActivityManager).switchUser(mForegroundUserId);
+
+ assertThat(mCarUserManagerHelper.switchToUserId(mForegroundUserId)).isFalse();
+ verify(mActivityManager, never()).switchUser(mForegroundUserId);
+ }
+
+ @Test
+ public void testCannotSwitchIfSwitchingNotAllowed() {
+ int userIdToSwitchTo = mForegroundUserId + 2;
+ doReturn(true).when(mActivityManager).switchUser(userIdToSwitchTo);
+ doReturn(true).when(mUserManager).hasUserRestriction(UserManager.DISALLOW_USER_SWITCH);
+ assertThat(mCarUserManagerHelper.switchToUserId(userIdToSwitchTo)).isFalse();
+ verify(mActivityManager, never()).switchUser(userIdToSwitchTo);
+ }
+
+ @Test
public void testGetUserIcon() {
mCarUserManagerHelper.getUserIcon(mCurrentProcessUser);
verify(mUserManager).getUserIcon(mCurrentProcessUser.id);
diff --git a/tests/carservice_unit_test/src/com/android/car/user/CarUserServiceTest.java b/tests/carservice_unit_test/src/com/android/car/user/CarUserServiceTest.java
index 48d447b..74f1a84 100644
--- a/tests/carservice_unit_test/src/com/android/car/user/CarUserServiceTest.java
+++ b/tests/carservice_unit_test/src/com/android/car/user/CarUserServiceTest.java
@@ -40,7 +40,6 @@
import org.mockito.MockitoAnnotations;
import java.util.ArrayList;
-import java.util.List;
/**
* This class contains unit tests for the {@link CarUserService}.
@@ -107,20 +106,6 @@
}
/**
- * Test that the {@link CarUserService} starts up a secondary admin user upon first run.
- */
- @Test
- public void testStartsSecondaryAdminUserOnFirstRun() {
- UserInfo admin = mockAdmin(/* adminId= */ 10);
-
- mCarUserService.onReceive(mMockContext,
- new Intent(Intent.ACTION_LOCKED_BOOT_COMPLETED));
-
- verify(mCarUserManagerHelper).createNewAdminUser(CarUserService.OWNER_NAME);
- verify(mCarUserManagerHelper).switchToUser(admin);
- }
-
- /**
* Test that the {@link CarUserService} disable modify account for user 0 upon first run.
*/
@Test
@@ -154,47 +139,6 @@
}
/**
- * Test that the {@link CarUserService} updates last active user to the first admin user
- * on first run.
- */
- @Test
- public void testUpdateLastActiveUserOnFirstRun() {
- UserInfo admin = mockAdmin(/* adminId= */ 10);
-
- mCarUserService.onReceive(mMockContext,
- new Intent(Intent.ACTION_LOCKED_BOOT_COMPLETED));
-
- verify(mCarUserManagerHelper)
- .setLastActiveUser(admin.id, /* skipGlobalSetting= */ false);
- }
-
- /**
- * Test that the {@link CarUserService} starts up the last active user on reboot.
- */
- @Test
- public void testStartsLastActiveUserOnReboot() {
- List<UserInfo> users = new ArrayList<>();
-
- int adminUserId = 10;
- UserInfo admin = new UserInfo(adminUserId, CarUserService.OWNER_NAME, UserInfo.FLAG_ADMIN);
-
- int secUserId = 11;
- UserInfo secUser =
- new UserInfo(secUserId, CarUserService.OWNER_NAME, UserInfo.FLAG_ADMIN);
-
- users.add(admin);
- users.add(secUser);
-
- doReturn(users).when(mCarUserManagerHelper).getAllUsers();
- doReturn(secUserId).when(mCarUserManagerHelper).getInitialUser();
-
- mCarUserService.onReceive(mMockContext,
- new Intent(Intent.ACTION_LOCKED_BOOT_COMPLETED));
-
- verify(mCarUserManagerHelper).switchToUserId(secUserId);
- }
-
- /**
* Test that the {@link CarUserService} updates last active user on user switch intent.
*/
@Test
@@ -226,8 +170,10 @@
}
private UserInfo mockAdmin(int adminId) {
- UserInfo admin = new UserInfo(adminId, CarUserService.OWNER_NAME, UserInfo.FLAG_ADMIN);
- doReturn(admin).when(mCarUserManagerHelper).createNewAdminUser(CarUserService.OWNER_NAME);
+ UserInfo admin = new UserInfo(adminId, CarUserManagerHelper.DEFAULT_FIRST_ADMIN_NAME,
+ UserInfo.FLAG_ADMIN);
+ doReturn(admin).when(mCarUserManagerHelper)
+ .createNewAdminUser(CarUserManagerHelper.DEFAULT_FIRST_ADMIN_NAME);
return admin;
}
}
diff --git a/tests/usb/AoapHostApp/Android.mk b/tests/usb/AoapHostApp/Android.mk
index 9fc286a..b020473 100644
--- a/tests/usb/AoapHostApp/Android.mk
+++ b/tests/usb/AoapHostApp/Android.mk
@@ -32,7 +32,7 @@
LOCAL_PROGUARD_ENABLED := disabled
-LOCAL_STATIC_JAVA_LIBRARIES := junit
-include packages/services/Car/car-support-lib/car-support.mk
+LOCAL_STATIC_JAVA_LIBRARIES := junit \
+ android.car
include $(BUILD_PACKAGE)
diff --git a/tests/vehiclehal_test/assets/car_diagnostic_test.json b/tests/vehiclehal_test/assets/car_diagnostic_test.json
new file mode 100644
index 0000000..d81926e
--- /dev/null
+++ b/tests/vehiclehal_test/assets/car_diagnostic_test.json
@@ -0,0 +1,2712 @@
+[
+ {
+ "timestamp": 1000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [42.22222, 64, 214.0625, 0.0, 0.0, 0.0, 0.0, 0.0, 3080, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 31.764706, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 2000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [42.22222, 64, 216.40625, 0.0, 0.0, 0.0, 0.0, 0.0, 3084, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 20, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 3000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [41.77778, 64, 214.0625, 0.0, 0.0, 0.0, 0.0, 0.0, 3078, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 31.764706, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 4000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [40.88889, 64, 207.03125, 0.0, 0.0, 0.0, 0.0, 0.0, 2873, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 31.764706, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 5000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [40.88889, 65, 214.0625, 0.0, 0.0, 0.0, 0.0, 0.0, 3078, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 31.764706, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 26, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 6000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [41.333332, 65, 200, 0.0, 0.0, 0.0, 0.0, 0.0, 2869, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 31.764706, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 7000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [52, 66, 230.46875, 0.0, 0.0, 0.0, 0.0, 0.0, 3090, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 30, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 8000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [68.44444, 66, 214.0625, 0.0, 0.0, 0.0, 0.0, 0.0, 4110, 1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 34.11765, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 9000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [51.11111, 66, 223.4375, 0.0, 0.0, 0.0, 0.0, 0.0, 3633, 5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 30.19608, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 34, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 10000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [50.666668, 67, 230.46875, 0.0, 0.0, 0.0, 0.0, 0.0, 3135, 4, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.941177, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 36, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 11000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [48.444443, 67, 228.125, 0.0, 0.0, 0.0, 0.0, 0.0, 3125, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 27.450981, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 38, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 12000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [55.555557, 68, 209.375, 0.0, 0.0, 0.0, 0.0, 0.0, 2857, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 26.27451, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 40, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 13000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [82.666664, 68, 202.34375, 0.0, 0.0, 0.0, 0.0, 0.0, 4899, 6, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 17.254902, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 42, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 14000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [45.333332, 68, 237.5, 0.0, 0.0, 0.0, 0.0, 0.0, 8483, 17, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.941177, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 44, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 15000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [28, 69, 188.28125, 0.0, 0.0, 0.0, 0.0, 0.0, 5158, 18, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 34.11765, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 46, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 16000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [36, 69, 216.40625, 0.0, 0.0, 0.0, 0.0, 0.0, 6184, 20, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 34.11765, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 48, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 17000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [31.11111, 70, 200, 0.0, 0.0, 0.0, 0.0, 0.0, 6207, 21, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 30.19608, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 50, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 18000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [28.88889, 70, 192.96875, 0.0, 0.0, 0.0, 0.0, 0.0, 5409, 19, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 36.47059, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 19000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [92.888885, 71, 200, 0.0, 0.0, 0.0, 0.0, 0.0, 5653, 18, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 24.705883, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 54, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 20000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [31.555555, 71, 209.375, 0.0, 0.0, 0.0, 0.0, 0.0, 7988, 26, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.941177, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 21000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [33.333332, 72, 176.5625, 0.0, 0.0, 0.0, 0.0, 0.0, 4134, 21, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.941177, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 58, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 22000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [49.333332, 72, 192.96875, 0.0, 0.0, 0.0, 0.0, 0.0, 3109, 14, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 30.19608, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 60, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 23000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "P0420",
+ "floatValues": [49.333332, 72, 192.96875, 0.0, 0.0, 0.0, 0.0, 0.0, 3109, 14, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 30.19608, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 60, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896065
+ },
+ {
+ "timestamp": 24000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [44.88889, 73, 223.4375, 0.0, 0.0, 0.0, 0.0, 0.0, 3635, 16, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 28.62745, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 62, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 25000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [45.77778, 73, 228.125, 0.0, 0.0, 0.0, 0.0, 0.0, 3619, 11, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 34.11765, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 26000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [36, 74, 216.40625, 0.0, 0.0, 0.0, 0.0, 0.0, 4637, 10, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 35.686275, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 66, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 27000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [36, 74, 228.125, 0.0, 0.0, 0.0, 0.0, 0.0, 7199, 15, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 30.19608, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 28000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [47.555557, 75, 211.71875, 0.0, 0.0, 0.0, 0.0, 0.0, 3894, 11, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 24.705883, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 70, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 29000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [48, 75, 218.75, 0.0, 0.0, 0.0, 0.0, 0.0, 3108, 1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 27.450981, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 72, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 30000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [45.77778, 75, 216.40625, 0.0, 0.0, 0.0, 0.0, 0.0, 3087, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 27.450981, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 74, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 31000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [45.77778, 76, 214.0625, 0.0, 0.0, 0.0, 0.0, 0.0, 3091, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 76, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 32000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [45.77778, 76, 216.40625, 0.0, 0.0, 0.0, 0.0, 0.0, 3090, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 78, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 33000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [45.77778, 77, 214.0625, 0.0, 0.0, 0.0, 0.0, 0.0, 3083, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 30.19608, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 80, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 34000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [45.333332, 77, 211.71875, 0.0, 0.0, 0.0, 0.0, 0.0, 3080, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 30.19608, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 82, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 35000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [45.77778, 77, 216.40625, 0.0, 0.0, 0.0, 0.0, 0.0, 3078, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 84, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 36000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [45.77778, 78, 211.71875, 0.0, 0.0, 0.0, 0.0, 0.0, 3077, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 30.19608, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 86, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 37000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [46.22222, 78, 211.71875, 0.0, 0.0, 0.0, 0.0, 0.0, 3078, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 88, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 38000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [45.77778, 78, 214.0625, 0.0, 0.0, 0.0, 0.0, 0.0, 3082, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 31.37255, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 90, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 39000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [45.333332, 79, 209.375, 0.0, 0.0, 0.0, 0.0, 0.0, 3076, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 92, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 40000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [46.22222, 79, 214.0625, 0.0, 0.0, 0.0, 0.0, 0.0, 3080, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 30.588236, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 94, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 41000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [45.77778, 79, 209.375, 0.0, 0.0, 0.0, 0.0, 0.0, 2879, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 96, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 42000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [45.77778, 79, 204.6875, 0.0, 0.0, 0.0, 0.0, 0.0, 3076, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 43000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [45.77778, 80, 214.0625, 0.0, 0.0, 0.0, 0.0, 0.0, 3082, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 44000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [45.77778, 80, 204.6875, 0.0, 0.0, 0.0, 0.0, 0.0, 2877, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 102, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 45000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [45.77778, 80, 207.03125, 0.0, 0.0, 0.0, 0.0, 0.0, 3076, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 104, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 46000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [45.77778, 81, 211.71875, 0.0, 0.0, 0.0, 0.0, 0.0, 3077, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 106, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 47000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [45.77778, 81, 204.6875, 0.0, 0.0, 0.0, 0.0, 0.0, 3072, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 108, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 48000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [46.22222, 81, 207.03125, 0.0, 0.0, 0.0, 0.0, 0.0, 3082, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 49000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [45.77778, 82, 202.34375, 0.0, 0.0, 0.0, 0.0, 0.0, 2879, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 112, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 50000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [45.77778, 82, 202.34375, 0.0, 0.0, 0.0, 0.0, 0.0, 3080, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 114, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 51000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [46.22222, 82, 204.6875, 0.0, 0.0, 0.0, 0.0, 0.0, 3077, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 116, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 52000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [46.22222, 82, 202.34375, 0.0, 0.0, 0.0, 0.0, 0.0, 2877, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 118, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 53000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [46.22222, 83, 204.6875, 0.0, 0.0, 0.0, 0.0, 0.0, 3079, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 120, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 54000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [46.22222, 83, 200, 0.0, 0.0, 0.0, 0.0, 0.0, 3073, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 31.764706, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 122, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 55000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [46.666668, 83, 197.65625, 0.0, 0.0, 0.0, 0.0, 0.0, 3078, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 124, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 56000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [46.22222, 83, 204.6875, 0.0, 0.0, 0.0, 0.0, 0.0, 3082, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 126, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 57000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [46.22222, 84, 197.65625, 0.0, 0.0, 0.0, 0.0, 0.0, 3073, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 58000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [47.11111, 84, 200, 0.0, 0.0, 0.0, 0.0, 0.0, 3075, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 130, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 59000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [46.22222, 84, 197.65625, 0.0, 0.0, 0.0, 0.0, 0.0, 3081, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 132, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 60000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [46.22222, 85, 195.3125, 0.0, 0.0, 0.0, 0.0, 0.0, 2878, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 134, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 61000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [46.666668, 85, 200, 0.0, 0.0, 0.0, 0.0, 0.0, 3082, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 31.764706, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 136, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 62000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [46.666668, 85, 195.3125, 0.0, 0.0, 0.0, 0.0, 0.0, 2879, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 138, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 63000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [47.11111, 85, 195.3125, 0.0, 0.0, 0.0, 0.0, 0.0, 3074, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 64000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [46.666668, 86, 197.65625, 0.0, 0.0, 0.0, 0.0, 0.0, 3085, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 142, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 65000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [47.11111, 86, 188.28125, 0.0, 0.0, 0.0, 0.0, 0.0, 3072, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 27.450981, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 144, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 66000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [49.77778, 86, 209.375, 0.0, 0.0, 0.0, 0.0, 0.0, 7177, 11, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 22.745098, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 146, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 67000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [41.333332, 86, 192.96875, 0.0, 0.0, 0.0, 0.0, 0.0, 4126, 15, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 22.745098, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 148, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 68000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [77.333336, 86, 200, 0.0, 0.0, 0.0, 0.0, 0.0, 6438, 20, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 22.745098, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 150, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 69000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [112.888885, 86, 202.34375, 0.0, 0.0, 0.0, 0.0, 0.0, 8746, 30, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 8.627451, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 152, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 70000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [103.111115, 86, 211.71875, 0.0, 0.0, 0.0, 0.0, 0.0, 14082, 44, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 20.784313, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 154, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 71000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [73.333336, 86, 214.0625, 0.0, 0.0, 0.0, 0.0, 0.0, 15639, 54, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 26.27451, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 156, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 72000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [63.555557, 85, 200, 0.0, 0.0, 0.0, 0.0, 0.0, 10268, 59, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 30.19608, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 158, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 73000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [24, 85, 146.09375, 0.0, 0.0, 0.0, 0.0, 0.0, 5928, 60, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 34.901962, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 160, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 74000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [59.555557, 85, 188.28125, 0.0, 0.0, 0.0, 0.0, 0.0, 6418, 58, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 30.19608, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 162, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 75000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [34.22222, 85, 214.0625, 0.0, 0.0, 0.0, 0.0, 0.0, 6179, 59, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 34.11765, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 164, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 76000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [99.55556, 85, 197.65625, 0.0, 0.0, 0.0, 0.0, 0.0, 7483, 59, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 28.62745, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 166, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 77000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [96.888885, 86, 195.3125, 0.0, 0.0, 0.0, 0.0, 0.0, 6660, 63, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 168, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 78000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [54.666668, 86, 200, 0.0, 0.0, 0.0, 0.0, 0.0, 8460, 66, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 170, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 79000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [20, 86, 167.1875, 0.0, 0.0, 0.0, 0.0, 0.0, 5431, 56, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 31.764706, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 80000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [15.111111, 86, 200, 0.0, 0.0, 0.0, 0.0, 0.0, 4868, 48, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [4, 0, 0, 0, 0, 0, 0, 174, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 81000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [83.55556, 87, 209.375, 0.0, 0.0, 0.0, 0.0, 0.0, 7195, 47, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [4, 0, 0, 0, 0, 0, 0, 176, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 82000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [104, 87, 200, 0.0, 0.0, 0.0, 0.0, 0.0, 6423, 48, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 26.27451, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 178, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 83000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [112.888885, 87, 216.40625, 0.0, 0.0, 0.0, 0.0, 0.0, 11582, 55, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 22.745098, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 180, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 84000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [113.333336, 87, 216.40625, 0.0, 0.0, 0.0, 0.0, 0.0, 13336, 67, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 26.27451, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 182, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 85000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [24, 87, 174.21875, 0.0, 0.0, 0.0, 0.0, 0.0, 12304, 73, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 24.705883, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 184, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 86000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [20.88889, 87, 181.25, 0.0, 0.0, 0.0, 0.0, 0.0, 6717, 68, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 30.19608, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 186, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 87000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [20.444445, 86, 200, 0.0, 0.0, 0.0, 0.0, 0.0, 4654, 47, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [4, 0, 0, 0, 0, 0, 0, 188, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 88000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [29.333334, 86, 197.65625, 0.0, 0.0, 0.0, 0.0, 0.0, 3330, 30, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 34.901962, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 190, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 89000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [40.88889, 87, 197.65625, 0.0, 0.0, 0.0, 0.0, 0.0, 3097, 13, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 34.901962, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 192, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 90000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [45.77778, 87, 214.0625, 0.0, 0.0, 0.0, 0.0, 0.0, 3088, 2, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 34.11765, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 194, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 91000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [42.666668, 88, 209.375, 0.0, 0.0, 0.0, 0.0, 0.0, 3075, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 26.27451, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 196, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 92000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [41.77778, 88, 207.03125, 0.0, 0.0, 0.0, 0.0, 0.0, 3072, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 26.27451, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 198, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 93000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [41.77778, 88, 214.0625, 0.0, 0.0, 0.0, 0.0, 0.0, 3074, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 200, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 94000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [42.22222, 89, 204.6875, 0.0, 0.0, 0.0, 0.0, 0.0, 2873, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 33.333332, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 202, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 95000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [42.666668, 89, 207.03125, 0.0, 0.0, 0.0, 0.0, 0.0, 2878, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 204, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 96000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [42.666668, 89, 209.375, 0.0, 0.0, 0.0, 0.0, 0.0, 3072, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 206, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 97000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [42.666668, 90, 202.34375, 0.0, 0.0, 0.0, 0.0, 0.0, 2870, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 208, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 98000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [42.666668, 90, 209.375, 0.0, 0.0, 0.0, 0.0, 0.0, 3075, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 210, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 99000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [43.11111, 90, 204.6875, 0.0, 0.0, 0.0, 0.0, 0.0, 2872, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 212, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 100000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [43.11111, 91, 202.34375, 0.0, 0.0, 0.0, 0.0, 0.0, 3082, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 214, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 101000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [43.11111, 91, 209.375, 0.0, 0.0, 0.0, 0.0, 0.0, 3072, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 216, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 102000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [43.11111, 91, 204.6875, 0.0, 0.0, 0.0, 0.0, 0.0, 2879, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 218, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 103000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [43.555557, 91, 209.375, 0.0, 0.0, 0.0, 0.0, 0.0, 3079, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 220, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 104000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [43.11111, 91, 202.34375, 0.0, 0.0, 0.0, 0.0, 0.0, 2876, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 222, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 105000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [43.555557, 91, 197.65625, 0.0, 0.0, 0.0, 0.0, 0.0, 3074, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 224, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 106000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [43.555557, 91, 207.03125, 0.0, 0.0, 0.0, 0.0, 0.0, 3078, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 226, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 107000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [43.11111, 92, 197.65625, 0.0, 0.0, 0.0, 0.0, 0.0, 3074, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 228, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 108000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [43.555557, 92, 200, 0.0, 0.0, 0.0, 0.0, 0.0, 3076, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 230, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 109000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [43.555557, 92, 207.03125, 0.0, 0.0, 0.0, 0.0, 0.0, 3080, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 232, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 110000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [43.555557, 92, 197.65625, 0.0, 0.0, 0.0, 0.0, 0.0, 2878, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 234, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 111000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [43.555557, 92, 204.6875, 0.0, 0.0, 0.0, 0.0, 0.0, 3082, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 236, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 112000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [44.444443, 92, 200, 0.0, 0.0, 0.0, 0.0, 0.0, 3076, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 238, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 113000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [43.555557, 92, 197.65625, 0.0, 0.0, 0.0, 0.0, 0.0, 3075, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 240, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 114000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [43.555557, 92, 195.3125, 0.0, 0.0, 0.0, 0.0, 0.0, 2872, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 243, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 115000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [44.444443, 92, 197.65625, 0.0, 0.0, 0.0, 0.0, 0.0, 3077, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 244, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 116000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [44, 92, 202.34375, 0.0, 0.0, 0.0, 0.0, 0.0, 3083, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 246, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 117000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [44, 92, 200, 0.0, 0.0, 0.0, 0.0, 0.0, 3080, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 248, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 118000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [44, 92, 195.3125, 0.0, 0.0, 0.0, 0.0, 0.0, 3077, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 250, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 119000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [44, 92, 200, 0.0, 0.0, 0.0, 0.0, 0.0, 3081, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 252, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 120000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [44, 92, 192.96875, 0.0, 0.0, 0.0, 0.0, 0.0, 3080, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 254, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 121000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [44, 92, 195.3125, 0.0, 0.0, 0.0, 0.0, 0.0, 2879, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 256, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 122000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [44.444443, 92, 197.65625, 0.0, 0.0, 0.0, 0.0, 0.0, 3073, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 258, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 123000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [44.444443, 92, 188.28125, 0.0, 0.0, 0.0, 0.0, 0.0, 2879, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 260, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 124000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [44.444443, 92, 197.65625, 0.0, 0.0, 0.0, 0.0, 0.0, 3076, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 262, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 125000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [59.555557, 92, 197.65625, 0.0, 0.0, 0.0, 0.0, 0.0, 3104, 1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 30.19608, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 264, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 126000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [100.888885, 92, 204.6875, 0.0, 0.0, 0.0, 0.0, 0.0, 8255, 15, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 9.411765, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 266, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 127000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [99.55556, 92, 209.375, 0.0, 0.0, 0.0, 0.0, 0.0, 11276, 33, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 15.686275, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 268, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 128000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [90.666664, 92, 209.375, 0.0, 0.0, 0.0, 0.0, 0.0, 15618, 50, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 26.27451, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 270, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 129000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [111.55556, 90, 216.40625, 0.0, 0.0, 0.0, 0.0, 0.0, 13109, 63, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 30.19608, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 272, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 130000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [111.55556, 89, 211.71875, 0.0, 0.0, 0.0, 0.0, 0.0, 14343, 74, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 17.647058, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 274, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 131000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [21.777779, 88, 192.96875, 0.0, 0.0, 0.0, 0.0, 0.0, 15921, 83, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 9.803922, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 276, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 132000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [34.666668, 87, 183.59375, 0.0, 0.0, 0.0, 0.0, 0.0, 4400, 55, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 26.27451, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 278, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 133000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [30.666666, 87, 183.59375, 0.0, 0.0, 0.0, 0.0, 0.0, 3117, 32, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 28.62745, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 280, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 134000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [29.333334, 87, 197.65625, 0.0, 0.0, 0.0, 0.0, 0.0, 3108, 26, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 28.62745, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 282, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 135000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [32.88889, 87, 195.3125, 0.0, 0.0, 0.0, 0.0, 0.0, 3106, 21, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 34.11765, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 284, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 136000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [111.111115, 88, 207.03125, 0.0, 0.0, 0.0, 0.0, 0.0, 4115, 17, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 17.254902, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 286, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 137000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [112.44444, 89, 209.375, 0.0, 0.0, 0.0, 0.0, 0.0, 8991, 30, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 26.27451, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 288, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 138000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [95.55556, 89, 197.65625, 0.0, 0.0, 0.0, 0.0, 0.0, 9513, 43, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 28.62745, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 290, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 139000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [27.555555, 89, 195.3125, 0.0, 0.0, 0.0, 0.0, 0.0, 9518, 50, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 34.509804, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 292, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 140000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [19.555555, 89, 178.90625, 0.0, 0.0, 0.0, 0.0, 0.0, 6418, 49, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 30.19608, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 294, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 141000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [20.88889, 89, 188.28125, 0.0, 0.0, 0.0, 0.0, 0.0, 5173, 40, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 34.11765, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 296, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 142000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [28.444445, 89, 185.9375, 0.0, 0.0, 0.0, 0.0, 0.0, 4112, 32, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.941177, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 298, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 143000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [113.333336, 89, 202.34375, 0.0, 0.0, 0.0, 0.0, 0.0, 8720, 37, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 28.62745, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 300, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 144000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [109.333336, 89, 216.40625, 0.0, 0.0, 0.0, 0.0, 0.0, 16412, 52, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 12.54902, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 302, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 145000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [22.666666, 89, 178.90625, 0.0, 0.0, 0.0, 0.0, 0.0, 13828, 61, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.941177, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 304, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 146000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [28.88889, 88, 197.65625, 0.0, 0.0, 0.0, 0.0, 0.0, 6447, 61, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 34.11765, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 306, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 147000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [16.88889, 87, 200, 0.0, 0.0, 0.0, 0.0, 0.0, 5657, 56, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 30.19608, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 308, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 148000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [19.11111, 87, 200, 0.0, 0.0, 0.0, 0.0, 0.0, 4873, 48, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 35.686275, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [4, 0, 0, 0, 0, 0, 0, 310, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 149000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [27.11111, 87, 185.9375, 0.0, 0.0, 0.0, 0.0, 0.0, 3613, 34, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [4, 0, 0, 0, 0, 0, 0, 312, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 150000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [30.222221, 88, 202.34375, 0.0, 0.0, 0.0, 0.0, 0.0, 3131, 19, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 36.862747, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 314, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 151000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [36.444443, 88, 209.375, 0.0, 0.0, 0.0, 0.0, 0.0, 3844, 8, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 34.901962, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 316, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 152000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [43.555557, 88, 209.375, 0.0, 0.0, 0.0, 0.0, 0.0, 3080, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 28.62745, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 318, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 153000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [42.666668, 89, 197.65625, 0.0, 0.0, 0.0, 0.0, 0.0, 2866, 1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.941177, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 320, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 154000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [76, 89, 200, 0.0, 0.0, 0.0, 0.0, 0.0, 7457, 13, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 10.588236, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 322, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 155000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [105.77778, 90, 204.6875, 0.0, 0.0, 0.0, 0.0, 0.0, 9272, 27, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 15.686275, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 324, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 156000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [87.55556, 90, 211.71875, 0.0, 0.0, 0.0, 0.0, 0.0, 13585, 43, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 28.62745, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 326, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 157000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [42.666668, 89, 190.625, 0.0, 0.0, 0.0, 0.0, 0.0, 11024, 53, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 20.784313, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 328, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 158000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [18.222221, 88, 155.46875, 0.0, 0.0, 0.0, 0.0, 0.0, 6927, 51, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 28.62745, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 330, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 159000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [21.333334, 88, 157.8125, 0.0, 0.0, 0.0, 0.0, 0.0, 5148, 38, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 34.11765, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 332, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 160000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [26.222221, 88, 139.0625, 0.0, 0.0, 0.0, 0.0, 0.0, 3594, 29, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 26.27451, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 334, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 161000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [48.88889, 88, 185.9375, 0.0, 0.0, 0.0, 0.0, 0.0, 3350, 25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 18.82353, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 336, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 162000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [79.55556, 88, 202.34375, 0.0, 0.0, 0.0, 0.0, 0.0, 8456, 34, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 26.27451, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 338, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 163000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [30.666666, 89, 185.9375, 0.0, 0.0, 0.0, 0.0, 0.0, 6163, 40, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 36.47059, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 340, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 164000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [24, 89, 188.28125, 0.0, 0.0, 0.0, 0.0, 0.0, 4886, 32, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 30.588236, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 342, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 165000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [54.22222, 89, 192.96875, 0.0, 0.0, 0.0, 0.0, 0.0, 5130, 29, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 28.62745, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 344, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 166000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [112.888885, 89, 202.34375, 0.0, 0.0, 0.0, 0.0, 0.0, 9525, 38, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 26.27451, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 346, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 167000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [99.55556, 89, 202.34375, 0.0, 0.0, 0.0, 0.0, 0.0, 10513, 49, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 348, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 168000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [76.888885, 89, 202.34375, 0.0, 0.0, 0.0, 0.0, 0.0, 8248, 54, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.941177, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 350, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 169000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [59.11111, 89, 197.65625, 0.0, 0.0, 0.0, 0.0, 0.0, 8484, 59, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 352, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 170000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [74.22222, 89, 211.71875, 0.0, 0.0, 0.0, 0.0, 0.0, 5945, 61, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.941177, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 354, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 171000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [23.11111, 89, 178.90625, 0.0, 0.0, 0.0, 0.0, 0.0, 6197, 61, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 34.901962, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 356, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 172000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [20.88889, 89, 200, 0.0, 0.0, 0.0, 0.0, 0.0, 5904, 59, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 34.901962, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [4, 0, 0, 0, 0, 0, 0, 358, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 173000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [35.11111, 89, 207.03125, 0.0, 0.0, 0.0, 0.0, 0.0, 6154, 60, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 30.19608, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 360, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 174000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [16.88889, 90, 181.25, 0.0, 0.0, 0.0, 0.0, 0.0, 5636, 59, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 28.62745, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 362, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 175000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [54.666668, 90, 200, 0.0, 0.0, 0.0, 0.0, 0.0, 5411, 54, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 24.705883, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [4, 0, 0, 0, 0, 0, 0, 364, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 176000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [24.444445, 90, 195.3125, 0.0, 0.0, 0.0, 0.0, 0.0, 5688, 55, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.941177, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 366, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 177000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [48.88889, 90, 211.71875, 0.0, 0.0, 0.0, 0.0, 0.0, 5903, 55, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 26.27451, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 368, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 178000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [20.88889, 91, 204.6875, 0.0, 0.0, 0.0, 0.0, 0.0, 5162, 51, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 30.19608, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 370, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 179000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [24, 91, 188.28125, 0.0, 0.0, 0.0, 0.0, 0.0, 4124, 44, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 372, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 180000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [23.555555, 91, 181.25, 0.0, 0.0, 0.0, 0.0, 0.0, 3132, 37, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 34.901962, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 374, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 181000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [28, 91, 197.65625, 0.0, 0.0, 0.0, 0.0, 0.0, 3128, 24, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 34.901962, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 376, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 182000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [38.666668, 91, 200, 0.0, 0.0, 0.0, 0.0, 0.0, 3089, 15, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 39.607845, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 378, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 183000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [42.666668, 91, 209.375, 0.0, 0.0, 0.0, 0.0, 0.0, 2869, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 30.19608, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 380, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 184000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [39.555557, 91, 197.65625, 0.0, 0.0, 0.0, 0.0, 0.0, 2877, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 26.27451, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 382, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 185000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [39.11111, 92, 200, 0.0, 0.0, 0.0, 0.0, 0.0, 2871, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 28.62745, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 384, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 186000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [39.11111, 92, 197.65625, 0.0, 0.0, 0.0, 0.0, 0.0, 2872, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 387, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 187000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [39.11111, 92, 200, 0.0, 0.0, 0.0, 0.0, 0.0, 2870, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 30.19608, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 389, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 188000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [39.555557, 92, 197.65625, 0.0, 0.0, 0.0, 0.0, 0.0, 3073, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 391, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 189000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [39.555557, 92, 202.34375, 0.0, 0.0, 0.0, 0.0, 0.0, 3077, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 30.19608, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 392, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 190000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [40.444443, 92, 197.65625, 0.0, 0.0, 0.0, 0.0, 0.0, 2867, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 30.19608, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 394, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 191000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [40, 93, 202.34375, 0.0, 0.0, 0.0, 0.0, 0.0, 3072, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 30.19608, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 396, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 192000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [40, 93, 204.6875, 0.0, 0.0, 0.0, 0.0, 0.0, 3078, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 30.19608, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 398, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 193000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [40, 93, 197.65625, 0.0, 0.0, 0.0, 0.0, 0.0, 2875, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 30.588236, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 400, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 194000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [40, 93, 202.34375, 0.0, 0.0, 0.0, 0.0, 0.0, 3074, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 30.19608, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 402, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 195000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [40.444443, 93, 195.3125, 0.0, 0.0, 0.0, 0.0, 0.0, 2878, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 30.19608, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 404, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 196000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [40.444443, 93, 202.34375, 0.0, 0.0, 0.0, 0.0, 0.0, 3081, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 30.19608, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 406, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 197000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [40.444443, 93, 202.34375, 0.0, 0.0, 0.0, 0.0, 0.0, 3085, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 30.19608, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 408, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 198000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [40.444443, 93, 195.3125, 0.0, 0.0, 0.0, 0.0, 0.0, 2877, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 30.19608, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 410, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 199000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [40.88889, 93, 202.34375, 0.0, 0.0, 0.0, 0.0, 0.0, 3079, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 30.19608, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 412, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 200000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [40.88889, 93, 197.65625, 0.0, 0.0, 0.0, 0.0, 0.0, 3082, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 30.19608, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 414, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 201000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [40.444443, 94, 200, 0.0, 0.0, 0.0, 0.0, 0.0, 3079, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 30.19608, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 416, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 202000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [40.88889, 94, 204.6875, 0.0, 0.0, 0.0, 0.0, 0.0, 3077, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 30.19608, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 418, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 203000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [40.88889, 94, 192.96875, 0.0, 0.0, 0.0, 0.0, 0.0, 3076, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 30.19608, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 420, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 204000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [40.88889, 94, 195.3125, 0.0, 0.0, 0.0, 0.0, 0.0, 3075, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 30.19608, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 422, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 205000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [41.333332, 94, 202.34375, 0.0, 0.0, 0.0, 0.0, 0.0, 3080, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 30.19608, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 424, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 206000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [40.88889, 94, 195.3125, 0.0, 0.0, 0.0, 0.0, 0.0, 3080, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 30.19608, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 426, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 207000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [40.88889, 94, 197.65625, 0.0, 0.0, 0.0, 0.0, 0.0, 3081, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 30.19608, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 428, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 208000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [40.88889, 94, 192.96875, 0.0, 0.0, 0.0, 0.0, 0.0, 3085, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 30.19608, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 430, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 209000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [84, 94, 197.65625, 0.0, 0.0, 0.0, 0.0, 0.0, 3900, 2, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 11.372549, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 432, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 210000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [73.333336, 94, 207.03125, 0.0, 0.0, 0.0, 0.0, 0.0, 6937, 15, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 17.254902, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 434, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 211000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [100.888885, 94, 211.71875, 0.0, 0.0, 0.0, 0.0, 0.0, 10253, 30, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 10.588236, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 436, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 212000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [104, 94, 214.0625, 0.0, 0.0, 0.0, 0.0, 0.0, 14653, 46, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 22.745098, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 438, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 213000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [55.555557, 93, 209.375, 0.0, 0.0, 0.0, 0.0, 0.0, 17934, 59, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 24.705883, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 440, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 214000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [28.444445, 91, 190.625, 0.0, 0.0, 0.0, 0.0, 0.0, 8757, 62, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 22.745098, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 442, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 215000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [17.777779, 90, 188.28125, 0.0, 0.0, 0.0, 0.0, 0.0, 5642, 58, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 30.19608, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 444, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 216000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [25.333334, 89, 171.875, 0.0, 0.0, 0.0, 0.0, 0.0, 3630, 38, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 30.19608, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 446, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 217000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [25.777779, 89, 178.90625, 0.0, 0.0, 0.0, 0.0, 0.0, 3130, 27, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 30.19608, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 448, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 218000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [40, 90, 200, 0.0, 0.0, 0.0, 0.0, 0.0, 3091, 13, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.941177, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 450, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 219000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [43.11111, 90, 207.03125, 0.0, 0.0, 0.0, 0.0, 0.0, 3340, 4, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 30.19608, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 452, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 220000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [40.444443, 91, 197.65625, 0.0, 0.0, 0.0, 0.0, 0.0, 2874, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 30.19608, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 454, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 221000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [39.555557, 91, 202.34375, 0.0, 0.0, 0.0, 0.0, 0.0, 2877, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 27.450981, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 456, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 222000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [39.11111, 92, 197.65625, 0.0, 0.0, 0.0, 0.0, 0.0, 3074, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 458, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 223000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [39.555557, 92, 197.65625, 0.0, 0.0, 0.0, 0.0, 0.0, 2866, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 460, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 224000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [39.11111, 92, 202.34375, 0.0, 0.0, 0.0, 0.0, 0.0, 3072, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 462, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 225000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [39.555557, 93, 195.3125, 0.0, 0.0, 0.0, 0.0, 0.0, 2873, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 464, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 226000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [40, 93, 204.6875, 0.0, 0.0, 0.0, 0.0, 0.0, 3076, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 466, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 227000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [40.444443, 93, 200, 0.0, 0.0, 0.0, 0.0, 0.0, 3073, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 31.764706, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 468, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 228000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [40, 93, 200, 0.0, 0.0, 0.0, 0.0, 0.0, 3074, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 470, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 229000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [40.444443, 93, 204.6875, 0.0, 0.0, 0.0, 0.0, 0.0, 3074, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 472, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 230000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [40.444443, 93, 197.65625, 0.0, 0.0, 0.0, 0.0, 0.0, 2873, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 474, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 231000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [40.88889, 93, 200, 0.0, 0.0, 0.0, 0.0, 0.0, 3074, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 476, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 232000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [40.444443, 93, 204.6875, 0.0, 0.0, 0.0, 0.0, 0.0, 3074, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 478, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 233000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [40.444443, 94, 200, 0.0, 0.0, 0.0, 0.0, 0.0, 2879, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 480, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 234000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [40.88889, 94, 202.34375, 0.0, 0.0, 0.0, 0.0, 0.0, 3074, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 482, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 235000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [40.444443, 94, 197.65625, 0.0, 0.0, 0.0, 0.0, 0.0, 3079, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 484, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 236000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [40.444443, 94, 200, 0.0, 0.0, 0.0, 0.0, 0.0, 3074, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 486, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 237000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [40.88889, 94, 202.34375, 0.0, 0.0, 0.0, 0.0, 0.0, 3077, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 488, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 238000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [40.88889, 94, 195.3125, 0.0, 0.0, 0.0, 0.0, 0.0, 3073, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 490, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 239000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [41.333332, 94, 197.65625, 0.0, 0.0, 0.0, 0.0, 0.0, 2879, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 492, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 240000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [40.88889, 94, 200, 0.0, 0.0, 0.0, 0.0, 0.0, 3080, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 494, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 241000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [40.88889, 94, 192.96875, 0.0, 0.0, 0.0, 0.0, 0.0, 3072, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 496, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 242000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [41.333332, 94, 197.65625, 0.0, 0.0, 0.0, 0.0, 0.0, 3084, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 31.764706, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 498, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 243000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [41.333332, 94, 192.96875, 0.0, 0.0, 0.0, 0.0, 0.0, 3072, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 500, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 244000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [41.333332, 94, 195.3125, 0.0, 0.0, 0.0, 0.0, 0.0, 2878, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 502, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 245000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [41.333332, 94, 197.65625, 0.0, 0.0, 0.0, 0.0, 0.0, 3082, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 504, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 246000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [41.333332, 94, 195.3125, 0.0, 0.0, 0.0, 0.0, 0.0, 3073, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 506, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 247000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [41.77778, 94, 195.3125, 0.0, 0.0, 0.0, 0.0, 0.0, 3079, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 508, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 248000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [41.333332, 94, 192.96875, 0.0, 0.0, 0.0, 0.0, 0.0, 3075, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 510, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 249000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [41.333332, 94, 190.625, 0.0, 0.0, 0.0, 0.0, 0.0, 2874, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 512, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 250000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [41.333332, 94, 197.65625, 0.0, 0.0, 0.0, 0.0, 0.0, 3079, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 514, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 251000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [42.22222, 94, 192.96875, 0.0, 0.0, 0.0, 0.0, 0.0, 2879, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 31.764706, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 516, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 252000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [41.77778, 94, 192.96875, 0.0, 0.0, 0.0, 0.0, 0.0, 2872, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 518, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 253000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [41.77778, 94, 200, 0.0, 0.0, 0.0, 0.0, 0.0, 3077, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 520, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 254000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [41.77778, 94, 190.625, 0.0, 0.0, 0.0, 0.0, 0.0, 2872, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 31.764706, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 522, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 255000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [41.77778, 94, 195.3125, 0.0, 0.0, 0.0, 0.0, 0.0, 3079, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 524, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 256000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [41.77778, 94, 192.96875, 0.0, 0.0, 0.0, 0.0, 0.0, 2875, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 526, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 257000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [41.77778, 94, 192.96875, 0.0, 0.0, 0.0, 0.0, 0.0, 2879, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 528, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 258000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [42.22222, 94, 197.65625, 0.0, 0.0, 0.0, 0.0, 0.0, 3078, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 31.764706, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 530, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 259000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [41.77778, 94, 192.96875, 0.0, 0.0, 0.0, 0.0, 0.0, 3077, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.156864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 532, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 260000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [51.555557, 95, 209.375, 0.0, 0.0, 0.0, 0.0, 0.0, 5426, 5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 22.745098, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 534, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 261000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [66.22222, 96, 204.6875, 0.0, 0.0, 0.0, 0.0, 0.0, 9000, 18, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 27.450981, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 536, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 262000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [53.333332, 95, 204.6875, 0.0, 0.0, 0.0, 0.0, 0.0, 7996, 24, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 18.82353, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 538, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 263000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [109.333336, 95, 202.34375, 0.0, 0.0, 0.0, 0.0, 0.0, 6195, 29, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 10.588236, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 540, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 264000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [61.77778, 94, 204.6875, 0.0, 0.0, 0.0, 0.0, 0.0, 12839, 40, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 23.529411, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 542, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 265000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [111.55556, 94, 207.03125, 0.0, 0.0, 0.0, 0.0, 0.0, 10757, 49, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 27.450981, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 544, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 266000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [85.77778, 93, 202.34375, 0.0, 0.0, 0.0, 0.0, 0.0, 12836, 61, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 28.62745, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 546, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 267000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [34.22222, 92, 200, 0.0, 0.0, 0.0, 0.0, 0.0, 10042, 65, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 32.941177, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 548, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 268000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [111.55556, 92, 216.40625, 0.0, 0.0, 0.0, 0.0, 0.0, 9733, 66, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 26.27451, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 550, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 269000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [56.88889, 91, 202.34375, 0.0, 0.0, 0.0, 0.0, 0.0, 10302, 70, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 27.450981, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 552, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 270000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [111.111115, 91, 209.375, 0.0, 0.0, 0.0, 0.0, 0.0, 15104, 73, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 19.215687, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 554, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ },
+ {
+ "timestamp": 271000000,
+ "areaId": 0,
+ "value": {
+ "stringValue": "",
+ "floatValues": [75.111115, 91, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 16423, 86, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
+ "int32Values": [2, 0, 0, 0, 0, 0, 0, 556, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "prop": 299896064
+ }
+]
diff --git a/tests/vehiclehal_test/assets/car_info_test.json b/tests/vehiclehal_test/assets/car_info_test.json
new file mode 100644
index 0000000..90c9bdc
--- /dev/null
+++ b/tests/vehiclehal_test/assets/car_info_test.json
@@ -0,0 +1,20 @@
+[
+ {
+ "timestamp": 1526063903356950016,
+ "areaId": 0,
+ "value": 15000,
+ "prop": 291504388
+ },
+ {
+ "timestamp": 1526063903358950016,
+ "areaId": 0,
+ "value": 150000,
+ "prop": 291504390
+ },
+ {
+ "timestamp": 1526063903360950016,
+ "areaId": 0,
+ "value": "Test Car",
+ "prop": 286261505
+ }
+]
diff --git a/tests/vehiclehal_test/src/com/android/car/vehiclehal/test/CarDiagnosticTest.java b/tests/vehiclehal_test/src/com/android/car/vehiclehal/test/CarDiagnosticTest.java
new file mode 100644
index 0000000..b0dd2c7
--- /dev/null
+++ b/tests/vehiclehal_test/src/com/android/car/vehiclehal/test/CarDiagnosticTest.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2018 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.vehiclehal.test;
+
+import static junit.framework.Assert.assertTrue;
+
+import android.car.Car;
+import android.car.diagnostic.CarDiagnosticEvent;
+import android.car.diagnostic.CarDiagnosticManager;
+import android.car.diagnostic.FloatSensorIndex;
+import android.car.diagnostic.IntegerSensorIndex;
+import android.car.hardware.CarPropertyValue;
+import android.car.hardware.CarSensorManager;
+import android.hardware.automotive.vehicle.V2_0.VehiclePropValue;
+import android.hardware.automotive.vehicle.V2_0.VehicleProperty;
+import android.support.test.filters.LargeTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.util.Log;
+import android.util.SparseIntArray;
+
+import com.android.car.vehiclehal.VehiclePropValueBuilder;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.File;
+import java.time.Duration;
+import java.util.List;
+
+@RunWith(AndroidJUnit4.class)
+@LargeTest
+public class CarDiagnosticTest extends E2eCarTestBase {
+
+ private static final String TAG = Utils.concatTag(CarDiagnosticTest.class);
+
+ private static final Duration TEST_TIME_OUT = Duration.ofMinutes(5);
+
+ private static final String CAR_DIAGNOSTIC_TEST_JSON = "car_diagnostic_test.json";
+
+ private static final SparseIntArray DIAGNOSTIC_PROPERTY_MAP;
+
+ static {
+ DIAGNOSTIC_PROPERTY_MAP = new SparseIntArray();
+ DIAGNOSTIC_PROPERTY_MAP.append(
+ CarDiagnosticManager.FRAME_TYPE_LIVE, VehicleProperty.OBD2_LIVE_FRAME);
+ DIAGNOSTIC_PROPERTY_MAP.append(
+ CarDiagnosticManager.FRAME_TYPE_FREEZE, VehicleProperty.OBD2_FREEZE_FRAME);
+ }
+
+ private class CarDiagnosticListner implements CarDiagnosticManager.OnDiagnosticEventListener {
+
+ private VhalEventVerifier mVerifier;
+
+ CarDiagnosticListner(VhalEventVerifier verifier) {
+ mVerifier = verifier;
+ }
+
+ @Override
+ public void onDiagnosticEvent(CarDiagnosticEvent event) {
+ mVerifier.verify(fromCarDiagnosticEvent(event));
+ }
+ }
+
+ private static CarPropertyValue<VehiclePropValue.RawValue> fromCarDiagnosticEvent(
+ final CarDiagnosticEvent event) {
+ int prop = DIAGNOSTIC_PROPERTY_MAP.get(event.frameType);
+ VehiclePropValueBuilder builder = VehiclePropValueBuilder.newBuilder(prop);
+
+ for (int i = 0; i <= IntegerSensorIndex.LAST_SYSTEM; i++) {
+ builder.addIntValue(event.getSystemIntegerSensor(i, 0));
+ }
+ for (int i = 0; i <= FloatSensorIndex.LAST_SYSTEM; i++) {
+ builder.addFloatValue(event.getSystemFloatSensor(i, 0));
+ }
+
+ builder.setStringValue(event.dtc);
+ return new CarPropertyValue<>(prop, 0, builder.build().value);
+ }
+
+ @Test
+ public void testDiagnosticEvents() throws Exception {
+ Log.d(TAG, "Prepare Diagnostic test data");
+ List<CarPropertyValue> expectedEvents = getExpectedEvents(CAR_DIAGNOSTIC_TEST_JSON);
+ VhalEventVerifier verifier = new VhalEventVerifier(expectedEvents);
+
+ CarDiagnosticManager diagnosticManager = (CarDiagnosticManager) mCar.getCarManager(
+ Car.DIAGNOSTIC_SERVICE);
+
+ CarDiagnosticListner listner = new CarDiagnosticListner(verifier);
+
+ assertTrue("Failed to register for OBD2 diagnostic live frame.",
+ diagnosticManager.registerListener(listner,
+ CarDiagnosticManager.FRAME_TYPE_LIVE,
+ CarSensorManager.SENSOR_RATE_NORMAL));
+ assertTrue("Failed to register for OBD2 diagnostic freeze frame.",
+ diagnosticManager.registerListener(listner,
+ CarDiagnosticManager.FRAME_TYPE_FREEZE,
+ CarSensorManager.SENSOR_RATE_NORMAL));
+
+ File sharedJson = makeShareable(CAR_DIAGNOSTIC_TEST_JSON);
+ Log.d(TAG, "Send command to VHAL to start generation");
+ VhalEventGenerator diagnosticGenerator =
+ new JsonVhalEventGenerator(mVehicle).setJsonFile(sharedJson);
+ diagnosticGenerator.start();
+
+ Log.d(TAG, "Receiving and verifying VHAL events");
+ verifier.waitForEnd(TEST_TIME_OUT.toMillis());
+
+ Log.d(TAG, "Send command to VHAL to stop generation");
+ diagnosticGenerator.stop();
+ diagnosticManager.unregisterListener(listner);
+
+ assertTrue("Detected mismatched events: " + verifier.getResultString(),
+ verifier.getMismatchedEvents().isEmpty());
+ }
+}
diff --git a/tests/vehiclehal_test/src/com/android/car/vehiclehal/test/CarHvacTest.java b/tests/vehiclehal_test/src/com/android/car/vehiclehal/test/CarHvacTest.java
deleted file mode 100644
index 08544bd..0000000
--- a/tests/vehiclehal_test/src/com/android/car/vehiclehal/test/CarHvacTest.java
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Copyright (C) 2018 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.vehiclehal.test;
-
-import static org.junit.Assert.assertTrue;
-
-import static java.lang.Integer.toHexString;
-
-import android.car.Car;
-import android.car.hardware.CarPropertyConfig;
-import android.car.hardware.CarPropertyValue;
-import android.car.hardware.hvac.CarHvacManager;
-import android.car.hardware.hvac.CarHvacManager.CarHvacEventCallback;
-import android.hardware.automotive.vehicle.V2_0.VehiclePropValue;
-import android.hardware.automotive.vehicle.V2_0.VehicleProperty;
-import android.support.test.filters.LargeTest;
-import android.support.test.runner.AndroidJUnit4;
-import android.util.ArraySet;
-import android.util.Log;
-
-import org.junit.Assert;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.io.File;
-import java.time.Duration;
-import java.util.Set;
-
-
-/**
- * The test suite will execute end-to-end Car HVAC API test by generating HVAC property data from
- * default VHAL and verify those data on the fly. The test data is coming from assets/ folder in the
- * test APK and will be shared with VHAL to execute the test.
- */
-@RunWith(AndroidJUnit4.class)
-@LargeTest
-public class CarHvacTest extends E2eCarTestBase {
- private static final String TAG = Utils.concatTag(CarHvacTest.class);
-
- // Test should be completed within 1 hour as it only covers a finite set of HVAC properties
- private static final Duration TEST_TIME_OUT = Duration.ofHours(1);
-
- private static final String CAR_HVAC_TEST_JSON = "car_hvac_test.json";
-
- // Referred to hardware/interfaces/automotive/vehicle/2.0/types.hal, some of the HVAC properties
- // are in CONTINUOUS mode. They should be omitted when testing ON_CHANGE properties.
- private static final Set<Integer> CONTINUOUS_HVAC_PROPS;
-
- private Integer mNumPropEventsToSkip;
-
- static {
- CONTINUOUS_HVAC_PROPS = new ArraySet<>();
- CONTINUOUS_HVAC_PROPS.add(VehicleProperty.ENV_OUTSIDE_TEMPERATURE);
- }
-
-
- private class CarHvacOnChangeEventListener implements CarHvacEventCallback {
- private VhalEventVerifier mVerifier;
-
- CarHvacOnChangeEventListener(VhalEventVerifier verifier) {
- mVerifier = verifier;
- }
-
- @Override
- public void onChangeEvent(CarPropertyValue carPropertyValue) {
- VehiclePropValue event = Utils.fromHvacPropertyValue(carPropertyValue);
- if (!CONTINUOUS_HVAC_PROPS.contains(event.prop)) {
- synchronized (mNumPropEventsToSkip) {
- if (mNumPropEventsToSkip == 0) {
- mVerifier.verify(Utils.fromHvacPropertyValue(carPropertyValue));
- } else {
- mNumPropEventsToSkip--;
- }
- }
- }
- }
-
- @Override
- public void onErrorEvent(final int propertyId, final int zone) {
- Assert.fail("Error: propertyId=" + toHexString(propertyId) + " zone=" + zone);
- }
- }
-
- private Integer calculateNumPropEventsToSkip(CarHvacManager hvacMgr) {
- int numToSkip = 0;
- try {
- for (CarPropertyConfig c: hvacMgr.getPropertyList()) {
- if (!CONTINUOUS_HVAC_PROPS.contains(c.getPropertyId())) {
- numToSkip += c.getAreaCount();
- }
- }
- } catch (Exception e) {
- Log.d(TAG, "Unhandled exception thrown: ", e);
- }
- return Integer.valueOf(numToSkip);
- }
- @Test
- public void testHvacOperations() throws Exception {
- Log.d(TAG, "Prepare HVAC test data");
- VhalEventVerifier verifier = new VhalEventVerifier(getExpectedEvents(CAR_HVAC_TEST_JSON));
- File sharedJson = makeShareable(CAR_HVAC_TEST_JSON);
-
- Log.d(TAG, "Start listening to the HAL");
- CarHvacManager hvacMgr = (CarHvacManager) mCar.getCarManager(Car.HVAC_SERVICE);
- // Calculate number of properties to skip due to registration event
- mNumPropEventsToSkip = calculateNumPropEventsToSkip(hvacMgr);
- CarHvacEventCallback callback = new CarHvacOnChangeEventListener(verifier);
- hvacMgr.registerCallback(callback);
-
- Log.d(TAG, "Send command to VHAL to start generation");
- VhalEventGenerator hvacGenerator =
- new JsonVhalEventGenerator(mVehicle).setJsonFile(sharedJson);
- hvacGenerator.start();
-
- Log.d(TAG, "Receiving and verifying VHAL events");
- verifier.waitForEnd(TEST_TIME_OUT.toMillis());
-
- Log.d(TAG, "Send command to VHAL to stop generation");
- hvacGenerator.stop();
- hvacMgr.unregisterCallback(callback);
-
- assertTrue("Detected mismatched events: " + verifier.getResultString(),
- verifier.getMismatchedEvents().isEmpty());
- }
-}
diff --git a/tests/vehiclehal_test/src/com/android/car/vehiclehal/test/CarPropertyTest.java b/tests/vehiclehal_test/src/com/android/car/vehiclehal/test/CarPropertyTest.java
new file mode 100644
index 0000000..27579bd
--- /dev/null
+++ b/tests/vehiclehal_test/src/com/android/car/vehiclehal/test/CarPropertyTest.java
@@ -0,0 +1,206 @@
+/*
+ * Copyright (C) 2018 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.vehiclehal.test;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import static java.lang.Integer.toHexString;
+
+import android.car.Car;
+import android.car.hardware.CarPropertyConfig;
+import android.car.hardware.CarPropertyValue;
+import android.car.hardware.property.CarPropertyManager;
+import android.support.test.filters.LargeTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.util.ArraySet;
+import android.util.Log;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.File;
+import java.time.Duration;
+import java.util.List;
+
+/**
+ * The test suite will execute end-to-end Car Property API test by generating VHAL property data
+ * from default VHAL and verify those data on the fly. The test data is coming from assets/ folder
+ * in the test APK and will be shared with VHAL to execute the test.
+ */
+@RunWith(AndroidJUnit4.class)
+@LargeTest
+public class CarPropertyTest extends E2eCarTestBase {
+
+ private static final String TAG = Utils.concatTag(CarPropertyTest.class);
+
+ // Test should be completed within 10 minutes as it only covers a finite set of properties
+ private static final Duration TEST_TIME_OUT = Duration.ofMinutes(10);
+
+ private static final String CAR_HVAC_TEST_JSON = "car_hvac_test.json";
+ private static final String CAR_INFO_TEST_JSON = "car_info_test.json";
+
+ private class CarPropertyEventReceiver implements
+ CarPropertyManager.CarPropertyEventListener {
+
+ private VhalEventVerifier mVerifier;
+ private Integer mNumOfEventToSkip;
+
+ CarPropertyEventReceiver(VhalEventVerifier verifier, int numOfEventToSkip) {
+ mVerifier = verifier;
+ mNumOfEventToSkip = numOfEventToSkip;
+ }
+
+ @Override
+ public void onChangeEvent(CarPropertyValue carPropertyValue) {
+ Log.d(TAG, "Received event: " + carPropertyValue);
+ synchronized (mNumOfEventToSkip) {
+ if (mNumOfEventToSkip > 0) {
+ mNumOfEventToSkip--;
+ return;
+ }
+ }
+ mVerifier.verify(carPropertyValue);
+ }
+
+ @Override
+ public void onErrorEvent(final int propertyId, final int zone) {
+ Assert.fail("Error: propertyId=" + toHexString(propertyId) + " zone=" + zone);
+ }
+ }
+
+ private int countNumPropEventsToSkip(CarPropertyManager propMgr, ArraySet<Integer> props) {
+ int numToSkip = 0;
+ for (CarPropertyConfig c : propMgr.getPropertyList(props)) {
+ numToSkip += c.getAreaCount();
+ }
+ return numToSkip;
+ }
+
+ /**
+ * This test will let Default VHAL to generate HVAC data and verify on-the-fly in the test. It
+ * is simulating the HVAC actions coming from hard buttons in a car.
+ * @throws Exception
+ */
+ @Test
+ public void testHvacHardButtonOperations() throws Exception {
+ Log.d(TAG, "Prepare HVAC test data");
+ List<CarPropertyValue> expectedEvents = getExpectedEvents(CAR_HVAC_TEST_JSON);
+ VhalEventVerifier verifier = new VhalEventVerifier(expectedEvents);
+
+ CarPropertyManager propMgr = (CarPropertyManager) mCar.getCarManager(Car.PROPERTY_SERVICE);
+ assertNotNull("CarPropertyManager is null", propMgr);
+
+ ArraySet<Integer> props = new ArraySet<>();
+ for (CarPropertyValue event : expectedEvents) {
+ if (!props.contains(event.getPropertyId())) {
+ props.add(event.getPropertyId());
+ }
+ }
+
+ int numToSkip = countNumPropEventsToSkip(propMgr, props);
+ Log.d(TAG, String.format("Start listening to the HAL."
+ + " Skipping %d events for listener registration", numToSkip));
+ CarPropertyManager.CarPropertyEventListener receiver =
+ new CarPropertyEventReceiver(verifier, numToSkip);
+ for (Integer prop : props) {
+ propMgr.registerListener(receiver, prop, 0);
+ }
+
+ File sharedJson = makeShareable(CAR_HVAC_TEST_JSON);
+ Log.d(TAG, "Send command to VHAL to start generation");
+ VhalEventGenerator hvacGenerator =
+ new JsonVhalEventGenerator(mVehicle).setJsonFile(sharedJson);
+ hvacGenerator.start();
+
+ Log.d(TAG, "Receiving and verifying VHAL events");
+ verifier.waitForEnd(TEST_TIME_OUT.toMillis());
+
+ Log.d(TAG, "Send command to VHAL to stop generation");
+ hvacGenerator.stop();
+ propMgr.unregisterListener(receiver);
+
+ assertTrue("Detected mismatched events: " + verifier.getResultString(),
+ verifier.getMismatchedEvents().isEmpty());
+ }
+
+ /**
+ * This test will exercise on "set" calls to inject HVAC data in order to test the Car Property
+ * API end-to-end functionality.
+ * @throws Exception
+ */
+ @Test
+ @SuppressWarnings("unchecked")
+ public void testHvacSetGetOperations() throws Exception {
+ Log.d(TAG, "Prepare HVAC test data");
+ List<CarPropertyValue> expectedEvents = getExpectedEvents(CAR_HVAC_TEST_JSON);
+
+ CarPropertyManager propMgr = (CarPropertyManager) mCar.getCarManager(Car.PROPERTY_SERVICE);
+ assertNotNull("CarPropertyManager is null", propMgr);
+
+ final long waitForSetMillisecond = 2;
+ for (CarPropertyValue expectedEvent : expectedEvents) {
+ Class valueClass = expectedEvent.getValue().getClass();
+ propMgr.setProperty(valueClass,
+ expectedEvent.getPropertyId(),
+ expectedEvent.getAreaId(),
+ expectedEvent.getValue());
+
+ Thread.sleep(waitForSetMillisecond);
+ CarPropertyValue receivedEvent = propMgr.getProperty(valueClass,
+ expectedEvent.getPropertyId(), expectedEvent.getAreaId());
+ assertTrue("Mismatched events, expected: " + expectedEvent + ", received: "
+ + receivedEvent, Utils.areCarPropertyValuesEqual(expectedEvent, receivedEvent));
+ }
+ }
+
+ /**
+ * This test will load static vehicle information from test data file and verify them through
+ * get calls.
+ * @throws Exception
+ */
+ @Test
+ public void testStaticInfoOperations() throws Exception {
+ Log.d(TAG, "Prepare static car information");
+
+ List<CarPropertyValue> expectedEvents = getExpectedEvents(CAR_INFO_TEST_JSON);
+ CarPropertyManager propMgr = (CarPropertyManager) mCar.getCarManager(Car.PROPERTY_SERVICE);
+ assertNotNull("CarPropertyManager is null", propMgr);
+
+ File sharedJson = makeShareable(CAR_INFO_TEST_JSON);
+ Log.d(TAG, "Send command to VHAL to start generation");
+ VhalEventGenerator infoGenerator =
+ new JsonVhalEventGenerator(mVehicle).setJsonFile(sharedJson);
+ infoGenerator.start();
+
+ // Wait for some time to ensure information is all loaded
+ // It is assuming the test data is not very large
+ Thread.sleep(2000);
+
+ Log.d(TAG, "Send command to VHAL to stop generation");
+ infoGenerator.stop();
+
+ for (CarPropertyValue expectedEvent : expectedEvents) {
+ CarPropertyValue actualEvent = propMgr.getProperty(
+ expectedEvent.getPropertyId(), expectedEvent.getAreaId());
+ assertTrue(String.format(
+ "Mismatched car information data, actual: %s, expected: %s",
+ actualEvent, expectedEvent),
+ Utils.areCarPropertyValuesEqual(actualEvent, expectedEvent));
+ }
+ }
+}
diff --git a/tests/vehiclehal_test/src/com/android/car/vehiclehal/test/E2eCarTestBase.java b/tests/vehiclehal_test/src/com/android/car/vehiclehal/test/E2eCarTestBase.java
index 5960422..9485d80 100644
--- a/tests/vehiclehal_test/src/com/android/car/vehiclehal/test/E2eCarTestBase.java
+++ b/tests/vehiclehal_test/src/com/android/car/vehiclehal/test/E2eCarTestBase.java
@@ -19,12 +19,12 @@
import static org.junit.Assume.assumeTrue;
import android.car.Car;
+import android.car.hardware.CarPropertyValue;
import android.content.ComponentName;
import android.content.Context;
import android.content.ServiceConnection;
import android.hardware.automotive.vehicle.V2_0.IVehicle;
import android.hardware.automotive.vehicle.V2_0.StatusCode;
-import android.hardware.automotive.vehicle.V2_0.VehiclePropValue;
import android.os.ConditionVariable;
import android.os.FileUtils;
import android.os.IBinder;
@@ -82,7 +82,7 @@
}
}
- protected List<VehiclePropValue> getExpectedEvents(String fileName)
+ protected List<CarPropertyValue> getExpectedEvents(String fileName)
throws IOException, JSONException {
try (InputStream in = mContext.getAssets().open(fileName)) {
Log.d(TAG, "Reading golden test data" + fileName);
diff --git a/tests/vehiclehal_test/src/com/android/car/vehiclehal/test/JsonVhalEventGenerator.java b/tests/vehiclehal_test/src/com/android/car/vehiclehal/test/JsonVhalEventGenerator.java
index 702f5f0..4560b8c 100644
--- a/tests/vehiclehal_test/src/com/android/car/vehiclehal/test/JsonVhalEventGenerator.java
+++ b/tests/vehiclehal_test/src/com/android/car/vehiclehal/test/JsonVhalEventGenerator.java
@@ -28,6 +28,9 @@
class JsonVhalEventGenerator implements VhalEventGenerator {
+ // Exactly one iteration is required for JSON-based end-to-end test
+ private static final int NUM_OF_ITERATION = 1;
+
private IVehicle mVehicle;
private File mFile;
@@ -47,7 +50,7 @@
public void start() throws RemoteException {
VehiclePropValue request =
VehiclePropValueBuilder.newBuilder(GENERATE_FAKE_DATA_CONTROLLING_PROPERTY)
- .addIntValue(CMD_START_JSON)
+ .addIntValue(CMD_START_JSON, NUM_OF_ITERATION)
.setStringValue(mFile.getAbsolutePath())
.build();
assertEquals(StatusCode.OK, mVehicle.set(request));
@@ -58,6 +61,7 @@
VehiclePropValue request =
VehiclePropValueBuilder.newBuilder(GENERATE_FAKE_DATA_CONTROLLING_PROPERTY)
.addIntValue(CMD_STOP_JSON)
+ .setStringValue(mFile.getAbsolutePath())
.build();
assertEquals(StatusCode.OK, mVehicle.set(request));
}
diff --git a/tests/vehiclehal_test/src/com/android/car/vehiclehal/test/Utils.java b/tests/vehiclehal_test/src/com/android/car/vehiclehal/test/Utils.java
index 6a4b496..496b504 100644
--- a/tests/vehiclehal_test/src/com/android/car/vehiclehal/test/Utils.java
+++ b/tests/vehiclehal_test/src/com/android/car/vehiclehal/test/Utils.java
@@ -16,13 +16,10 @@
package com.android.car.vehiclehal.test;
-import static java.lang.Integer.toHexString;
-
import android.car.hardware.CarPropertyValue;
import android.hardware.automotive.vehicle.V2_0.IVehicle;
import android.hardware.automotive.vehicle.V2_0.VehiclePropConfig;
import android.hardware.automotive.vehicle.V2_0.VehiclePropValue;
-import android.os.HidlSupport;
import android.os.RemoteException;
import android.util.Log;
@@ -102,55 +99,13 @@
* @param value2
* @return true if equal
*/
- static boolean areVehiclePropValuesEqual(final VehiclePropValue value1,
- final VehiclePropValue value2) {
+ static boolean areCarPropertyValuesEqual(final CarPropertyValue value1,
+ final CarPropertyValue value2) {
return value1 == value2
|| value1 != null
&& value2 != null
- && value1.prop == value2.prop
- && value1.areaId == value2.areaId
- && HidlSupport.deepEquals(value1.value, value2.value);
- }
-
- /**
- * The method will convert prop ID to hexadecimal format, and omit timestamp and status
- *
- * @param value
- * @return String
- */
- static String vehiclePropValueToString(final VehiclePropValue value) {
- return "{.prop = 0x" + toHexString(value.prop)
- + ", .areaId = " + value.areaId
- + ", .value = " + value.value + "}";
- }
-
- static VehiclePropValue fromHvacPropertyValue(CarPropertyValue value) {
- VehiclePropValueBuilder builder =
- VehiclePropValueBuilder.newBuilder(
- VhalPropMaps.getHvacVhalProp(value.getPropertyId()));
- return fromCarPropertyValue(value, builder);
- }
-
- private static VehiclePropValue fromCarPropertyValue(
- CarPropertyValue value, VehiclePropValueBuilder builder) {
- builder.setAreaId(value.getAreaId()).setTimestamp(value.getTimestamp());
-
- //TODO: Consider move this conversion to VehiclePropValueBuilder
- Object o = value.getValue();
- if (o instanceof Boolean) {
- builder.addIntValue((boolean) o ? 1 : 0);
- } else if (o instanceof Integer) {
- builder.addIntValue((int) o);
- } else if (o instanceof Float) {
- builder.addFloatValue((float) o);
- } else if (o instanceof Long) {
- builder.setInt64Value((long) o);
- } else if (o instanceof String) {
- builder.setStringValue((String) o);
- } else { //TODO: Add support for MIXED type
- throw new IllegalArgumentException("Unrecognized car property value type, "
- + o.getClass());
- }
- return builder.build();
+ && value1.getPropertyId() == value2.getPropertyId()
+ && value1.getAreaId() == value2.getAreaId()
+ && value1.getValue().equals(value2.getValue());
}
}
diff --git a/tests/vehiclehal_test/src/com/android/car/vehiclehal/test/VhalEventVerifier.java b/tests/vehiclehal_test/src/com/android/car/vehiclehal/test/VhalEventVerifier.java
index 5ac92ca..62dbf5c 100644
--- a/tests/vehiclehal_test/src/com/android/car/vehiclehal/test/VhalEventVerifier.java
+++ b/tests/vehiclehal_test/src/com/android/car/vehiclehal/test/VhalEventVerifier.java
@@ -15,7 +15,7 @@
*/
package com.android.car.vehiclehal.test;
-import android.hardware.automotive.vehicle.V2_0.VehiclePropValue;
+import android.car.hardware.CarPropertyValue;
import android.os.ConditionVariable;
import java.util.ArrayList;
@@ -28,7 +28,7 @@
* The verifier will provide formatted result for all mismatched events in sequence.
*/
class VhalEventVerifier {
- private List<VehiclePropValue> mExpectedEvents;
+ private List<CarPropertyValue> mExpectedEvents;
// A pointer to keep track of the next expected event in the list
private int mIdx;
private List<MismatchedEventPair> mMismatchedEvents;
@@ -37,10 +37,10 @@
static class MismatchedEventPair {
public final int idx;
- public final VehiclePropValue expectedEvent;
- public final VehiclePropValue mismatchedEvent;
+ public final CarPropertyValue expectedEvent;
+ public final CarPropertyValue mismatchedEvent;
- MismatchedEventPair(VehiclePropValue expectedEvent, VehiclePropValue mismatchedEvent,
+ MismatchedEventPair(CarPropertyValue expectedEvent, CarPropertyValue mismatchedEvent,
int idx) {
this.idx = idx;
this.expectedEvent = expectedEvent;
@@ -48,7 +48,7 @@
}
}
- VhalEventVerifier(List<VehiclePropValue> expectedEvents) {
+ VhalEventVerifier(List<CarPropertyValue> expectedEvents) {
mExpectedEvents = expectedEvents;
mIdx = 0;
mMismatchedEvents = new ArrayList<>();
@@ -62,12 +62,12 @@
*
* @param nextEvent to be verified
*/
- public void verify(VehiclePropValue nextEvent) {
+ public void verify(CarPropertyValue nextEvent) {
if (mIdx >= mExpectedEvents.size()) {
return;
}
- VehiclePropValue expectedEvent = mExpectedEvents.get(mIdx);
- if (!Utils.areVehiclePropValuesEqual(expectedEvent, nextEvent)) {
+ CarPropertyValue expectedEvent = mExpectedEvents.get(mIdx);
+ if (!Utils.areCarPropertyValuesEqual(expectedEvent, nextEvent)) {
mMismatchedEvents.add(new MismatchedEventPair(expectedEvent, nextEvent, mIdx));
}
if (++mIdx == mExpectedEvents.size()) {
@@ -87,8 +87,8 @@
StringBuilder resultBuilder = new StringBuilder();
for (MismatchedEventPair pair : mMismatchedEvents) {
resultBuilder.append("Index " + pair.idx + ": Expected "
- + Utils.vehiclePropValueToString(pair.expectedEvent) + ", Received "
- + Utils.vehiclePropValueToString(pair.mismatchedEvent) + "\n");
+ + pair.expectedEvent + ", Received "
+ + pair.mismatchedEvent + "\n");
}
return resultBuilder.toString();
}
diff --git a/tests/vehiclehal_test/src/com/android/car/vehiclehal/test/VhalJsonReader.java b/tests/vehiclehal_test/src/com/android/car/vehiclehal/test/VhalJsonReader.java
index bf4e32f..7731273 100644
--- a/tests/vehiclehal_test/src/com/android/car/vehiclehal/test/VhalJsonReader.java
+++ b/tests/vehiclehal_test/src/com/android/car/vehiclehal/test/VhalJsonReader.java
@@ -17,7 +17,7 @@
import static java.lang.Integer.toHexString;
-import android.hardware.automotive.vehicle.V2_0.VehiclePropValue;
+import android.car.hardware.CarPropertyValue;
import android.hardware.automotive.vehicle.V2_0.VehiclePropertyType;
import com.android.car.vehiclehal.VehiclePropValueBuilder;
@@ -44,11 +44,15 @@
private static final String JSON_FIELD_AREA_ID = "areaId";
private static final String JSON_FIELD_TIMESTAMP = "timestamp";
private static final String JSON_FIELD_VALUE = "value";
+ private static final String JSON_FIELD_INT32_VALUES = "int32Values";
+ private static final String JSON_FIELD_INT64_VALUES = "int64Values";
+ private static final String JSON_FIELD_FLOAT_VALUES = "floatValues";
+ private static final String JSON_FIELD_STRING_VALUE = "stringValue";
- public static List<VehiclePropValue> readFromJson(InputStream in)
+ public static List<CarPropertyValue> readFromJson(InputStream in)
throws IOException, JSONException {
JSONArray rawEvents = new JSONArray(readJsonString(in));
- List<VehiclePropValue> events = new ArrayList<>();
+ List<CarPropertyValue> events = new ArrayList<>();
for (int i = 0; i < rawEvents.length(); i++) {
events.add(getEvent(rawEvents.getJSONObject(i)));
}
@@ -64,32 +68,64 @@
return builder.toString();
}
- private static VehiclePropValue getEvent(JSONObject rawEvent) throws JSONException {
+ private static CarPropertyValue<?> getEvent(JSONObject rawEvent) throws JSONException {
int prop = rawEvent.getInt(JSON_FIELD_PROP);
- VehiclePropValueBuilder builder = VehiclePropValueBuilder.newBuilder(prop)
- .setAreaId(rawEvent.getInt(JSON_FIELD_AREA_ID))
- .setTimestamp(rawEvent.getLong(JSON_FIELD_TIMESTAMP));
+ int areaId = rawEvent.getInt(JSON_FIELD_AREA_ID);
+ long timestamp = rawEvent.getLong(JSON_FIELD_TIMESTAMP);
switch (prop & VehiclePropertyType.MASK) {
case VehiclePropertyType.BOOLEAN:
+ return new CarPropertyValue<>(prop, areaId, CarPropertyValue.STATUS_AVAILABLE,
+ timestamp, rawEvent.getInt(JSON_FIELD_VALUE) != 0);
case VehiclePropertyType.INT32:
- builder.addIntValue(rawEvent.getInt(JSON_FIELD_VALUE));
- break;
+ return new CarPropertyValue<>(prop, areaId, CarPropertyValue.STATUS_AVAILABLE,
+ timestamp, rawEvent.getInt(JSON_FIELD_VALUE));
case VehiclePropertyType.INT64:
- builder.setInt64Value(rawEvent.getLong(JSON_FIELD_VALUE));
- break;
+ return new CarPropertyValue<>(prop, areaId, CarPropertyValue.STATUS_AVAILABLE,
+ timestamp, rawEvent.getLong(JSON_FIELD_VALUE));
case VehiclePropertyType.FLOAT:
- builder.addFloatValue((float) rawEvent.getDouble(JSON_FIELD_VALUE));
- break;
+ return new CarPropertyValue<>(prop, areaId,
+ CarPropertyValue.STATUS_AVAILABLE, timestamp,
+ (float) rawEvent.getDouble(JSON_FIELD_VALUE));
case VehiclePropertyType.STRING:
- builder.setStringValue(rawEvent.getString(JSON_FIELD_VALUE));
- break;
- //TODO: Add VehiclePropertyType.MIXED type support
+ return new CarPropertyValue<>(prop, areaId, CarPropertyValue.STATUS_AVAILABLE,
+ timestamp, rawEvent.getString(JSON_FIELD_VALUE));
+ // TODO: CarPropertyValue API has not supported VehiclePropertyType.MIXED type yet.
+ // Here is a temporary solution to use VehiclePropValue.RawValue
+ case VehiclePropertyType.MIXED:
+ VehiclePropValueBuilder builder = VehiclePropValueBuilder.newBuilder(prop);
+ JSONObject rawValueJson = rawEvent.getJSONObject(JSON_FIELD_VALUE);
+ copyValuesArray(
+ builder, rawValueJson.optJSONArray(JSON_FIELD_INT32_VALUES), Integer.class);
+ copyValuesArray(
+ builder, rawValueJson.optJSONArray(JSON_FIELD_INT64_VALUES), Long.class);
+ copyValuesArray(
+ builder, rawValueJson.optJSONArray(JSON_FIELD_FLOAT_VALUES), Float.class);
+ builder.setStringValue(rawValueJson.getString(JSON_FIELD_STRING_VALUE));
+
+ return new CarPropertyValue<>(prop, areaId, CarPropertyValue.STATUS_AVAILABLE,
+ timestamp, builder.build().value);
default:
throw new IllegalArgumentException("Property type 0x"
+ toHexString(prop & VehiclePropertyType.MASK)
+ " is not supported in the test.");
}
- return builder.build();
+ }
+
+ private static void copyValuesArray(VehiclePropValueBuilder builder, JSONArray jsonArray,
+ Class clazz) throws JSONException {
+ if (jsonArray == null) {
+ return;
+ }
+ for (int i = 0; i < jsonArray.length(); i++) {
+ if (clazz == Integer.class) {
+ builder.addIntValue(jsonArray.getInt(i));
+ } else if (clazz == Long.class) {
+ // It is really "add" the value
+ builder.setInt64Value(jsonArray.getLong(i));
+ } else if (clazz == Float.class) {
+ builder.addFloatValue((float) jsonArray.getDouble(i));
+ } // TODO: Add support for byte array if required
+ }
}
}
diff --git a/tests/vehiclehal_test/src/com/android/car/vehiclehal/test/VhalPropMaps.java b/tests/vehiclehal_test/src/com/android/car/vehiclehal/test/VhalPropMaps.java
deleted file mode 100644
index f24cad6..0000000
--- a/tests/vehiclehal_test/src/com/android/car/vehiclehal/test/VhalPropMaps.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (C) 2018 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.vehiclehal.test;
-
-import android.car.hardware.hvac.CarHvacManager;
-import android.hardware.automotive.vehicle.V2_0.VehicleProperty;
-import android.util.SparseIntArray;
-
-class VhalPropMaps {
-
- private static final SparseIntArray HVAC_PROP_MAP;
-
- static {
- HVAC_PROP_MAP = new SparseIntArray();
- HVAC_PROP_MAP.put(CarHvacManager.ID_MIRROR_DEFROSTER_ON,
- VehicleProperty.HVAC_SIDE_MIRROR_HEAT);
- HVAC_PROP_MAP.put(CarHvacManager.ID_STEERING_WHEEL_HEAT,
- VehicleProperty.HVAC_STEERING_WHEEL_HEAT);
- HVAC_PROP_MAP.put(CarHvacManager.ID_OUTSIDE_AIR_TEMP,
- VehicleProperty.ENV_OUTSIDE_TEMPERATURE);
- HVAC_PROP_MAP.put(CarHvacManager.ID_TEMPERATURE_DISPLAY_UNITS,
- VehicleProperty.HVAC_TEMPERATURE_DISPLAY_UNITS);
- HVAC_PROP_MAP.put(CarHvacManager.ID_ZONED_TEMP_SETPOINT,
- VehicleProperty.HVAC_TEMPERATURE_SET);
- HVAC_PROP_MAP.put(CarHvacManager.ID_ZONED_TEMP_ACTUAL,
- VehicleProperty.HVAC_TEMPERATURE_CURRENT);
- HVAC_PROP_MAP.put(CarHvacManager.ID_ZONED_FAN_SPEED_SETPOINT,
- VehicleProperty.HVAC_FAN_SPEED);
- HVAC_PROP_MAP.put(CarHvacManager.ID_ZONED_FAN_SPEED_RPM,
- VehicleProperty.HVAC_ACTUAL_FAN_SPEED_RPM);
- HVAC_PROP_MAP.put(CarHvacManager.ID_ZONED_FAN_DIRECTION_AVAILABLE,
- VehicleProperty.HVAC_FAN_DIRECTION_AVAILABLE);
- HVAC_PROP_MAP.put(CarHvacManager.ID_ZONED_FAN_DIRECTION,
- VehicleProperty.HVAC_FAN_DIRECTION);
- HVAC_PROP_MAP.put(CarHvacManager.ID_ZONED_SEAT_TEMP,
- VehicleProperty.HVAC_SEAT_TEMPERATURE);
- HVAC_PROP_MAP.put(CarHvacManager.ID_ZONED_AC_ON,
- VehicleProperty.HVAC_AC_ON);
- HVAC_PROP_MAP.put(CarHvacManager.ID_ZONED_AUTOMATIC_MODE_ON,
- VehicleProperty.HVAC_AUTO_ON);
- HVAC_PROP_MAP.put(CarHvacManager.ID_ZONED_AIR_RECIRCULATION_ON,
- VehicleProperty.HVAC_RECIRC_ON);
- HVAC_PROP_MAP.put(CarHvacManager.ID_ZONED_MAX_AC_ON,
- VehicleProperty.HVAC_MAX_AC_ON);
- HVAC_PROP_MAP.put(CarHvacManager.ID_ZONED_DUAL_ZONE_ON,
- VehicleProperty.HVAC_DUAL_ON);
- HVAC_PROP_MAP.put(CarHvacManager.ID_ZONED_MAX_DEFROST_ON,
- VehicleProperty.HVAC_MAX_DEFROST_ON);
- HVAC_PROP_MAP.put(CarHvacManager.ID_ZONED_HVAC_POWER_ON,
- VehicleProperty.HVAC_POWER_ON);
- HVAC_PROP_MAP.put(CarHvacManager.ID_ZONED_HVAC_AUTO_RECIRC_ON,
- VehicleProperty.HVAC_AUTO_RECIRC_ON);
- HVAC_PROP_MAP.put(CarHvacManager.ID_WINDOW_DEFROSTER_ON,
- VehicleProperty.HVAC_DEFROSTER);
- }
-
- static int getHvacVhalProp(final int hvacProp) {
- return HVAC_PROP_MAP.get(hvacProp);
- }
-}
diff --git a/tools/emulator/vhal_consts_2_0.py b/tools/emulator/vhal_consts_2_0.py
index a9d9990..85351c0 100644
--- a/tools/emulator/vhal_consts_2_0.py
+++ b/tools/emulator/vhal_consts_2_0.py
@@ -138,13 +138,6 @@
STATUSCODE_ACCESS_DENIED = 0x4
STATUSCODE_INTERNAL_ERROR = 0x5
-# Wheel
-WHEEL_UNKNOWN = 0x0
-WHEEL_LEFT_FRONT = 0x1
-WHEEL_RIGHT_FRONT = 0x2
-WHEEL_LEFT_REAR = 0x4
-WHEEL_RIGHT_REAR = 0x8
-
# VehicleLightState
VEHICLELIGHTSTATE_OFF = 0x0
VEHICLELIGHTSTATE_ON = 0x1
@@ -266,17 +259,19 @@
VEHICLETURNSIGNAL_LEFT = 0x2
# EvConnectorType
-EVCONNECTORTYPE_EV_CONNECTOR_TYPE_UNKNOWN = 0x0
-EVCONNECTORTYPE_EV_CONNECTOR_TYPE_J1772 = 0x1
-EVCONNECTORTYPE_EV_CONNECTOR_TYPE_MENNEKES = 0x2
-EVCONNECTORTYPE_EV_CONNECTOR_TYPE_CHADEMO = 0x3
-EVCONNECTORTYPE_EV_CONNECTOR_TYPE_COMBO_1 = 0x4
-EVCONNECTORTYPE_EV_CONNECTOR_TYPE_COMBO_2 = 0x5
-EVCONNECTORTYPE_EV_CONNECTOR_TYPE_TESLA_ROADSTER = 0x6
-EVCONNECTORTYPE_EV_CONNECTOR_TYPE_TESLA_HPWC = 0x7
-EVCONNECTORTYPE_EV_CONNECTOR_TYPE_TESLA_SUPERCHARGER = 0x8
-EVCONNECTORTYPE_EV_CONNECTOR_TYPE_GBT = 0x9
-EVCONNECTORTYPE_EV_CONNECTOR_TYPE_OTHER = 0x65
+EVCONNECTORTYPE_UNKNOWN = 0x0
+EVCONNECTORTYPE_IEC_TYPE_1_AC = 0x1
+EVCONNECTORTYPE_IEC_TYPE_2_AC = 0x2
+EVCONNECTORTYPE_IEC_TYPE_3_AC = 0x3
+EVCONNECTORTYPE_IEC_TYPE_4_DC = 0x4
+EVCONNECTORTYPE_IEC_TYPE_1_CCS_DC = 0x5
+EVCONNECTORTYPE_IEC_TYPE_2_CCS_DC = 0x6
+EVCONNECTORTYPE_TESLA_ROADSTER = 0x7
+EVCONNECTORTYPE_TESLA_HPWC = 0x8
+EVCONNECTORTYPE_TESLA_SUPERCHARGER = 0x9
+EVCONNECTORTYPE_GBT_AC = 0xa
+EVCONNECTORTYPE_GBT_DC = 0xb
+EVCONNECTORTYPE_OTHER = 0x65
# VehiclePropertyType
VEHICLEPROPERTYTYPE_STRING = 0x100000
@@ -309,6 +304,13 @@
OBD2SECONDARYAIRSTATUS_FROM_OUTSIDE_OR_OFF = 0x4
OBD2SECONDARYAIRSTATUS_PUMP_ON_FOR_DIAGNOSTICS = 0x8
+# VehicleAreaWheel
+VEHICLEAREAWHEEL_UNKNOWN = 0x0
+VEHICLEAREAWHEEL_LEFT_FRONT = 0x1
+VEHICLEAREAWHEEL_RIGHT_FRONT = 0x2
+VEHICLEAREAWHEEL_LEFT_REAR = 0x4
+VEHICLEAREAWHEEL_RIGHT_REAR = 0x8
+
# VehicleGear
VEHICLEGEAR_GEAR_NEUTRAL = 0x1
VEHICLEGEAR_GEAR_REVERSE = 0x2
@@ -410,7 +412,7 @@
VEHICLEPROPERTY_EV_CHARGE_PORT_CONNECTED = 0x1120030b
VEHICLEPROPERTY_EV_BATTERY_INSTANTANEOUS_CHARGE_RATE = 0x1160030c
VEHICLEPROPERTY_RANGE_REMAINING = 0x11600308
-VEHICLEPROPERTY_TIRE_PRESSURE = 0x17e00309
+VEHICLEPROPERTY_TIRE_PRESSURE = 0x17600309
VEHICLEPROPERTY_GEAR_SELECTION = 0x11400400
VEHICLEPROPERTY_CURRENT_GEAR = 0x11400401
VEHICLEPROPERTY_PARKING_BRAKE_ON = 0x11200402
@@ -442,7 +444,6 @@
VEHICLEPROPERTY_HVAC_AUTO_RECIRC_ON = 0x15200512
VEHICLEPROPERTY_HVAC_SEAT_VENTILATION = 0x15400513
VEHICLEPROPERTY_ENV_OUTSIDE_TEMPERATURE = 0x11600703
-VEHICLEPROPERTY_ENV_CABIN_TEMPERATURE = 0x15600704
VEHICLEPROPERTY_AP_POWER_STATE_REQ = 0x11410a00
VEHICLEPROPERTY_AP_POWER_STATE_REPORT = 0x11410a01
VEHICLEPROPERTY_AP_POWER_BOOTUP_REASON = 0x11400a02